v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-api.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include <climits>
29 #include <csignal>
30 #include <string>
31 #include <map>
32 
33 #include "v8.h"
34 
35 #if V8_OS_POSIX
36 #include <unistd.h> // NOLINT
37 #endif
38 
39 #include "api.h"
40 #include "arguments.h"
41 #include "cctest.h"
42 #include "compilation-cache.h"
43 #include "cpu-profiler.h"
44 #include "execution.h"
45 #include "isolate.h"
46 #include "objects.h"
47 #include "parser.h"
48 #include "platform.h"
49 #include "snapshot.h"
50 #include "unicode-inl.h"
51 #include "utils.h"
52 #include "vm-state.h"
53 #include "../include/v8-util.h"
54 
55 static const bool kLogThreading = false;
56 
57 using ::v8::Boolean;
58 using ::v8::BooleanObject;
59 using ::v8::Context;
60 using ::v8::Extension;
61 using ::v8::Function;
62 using ::v8::FunctionTemplate;
63 using ::v8::Handle;
64 using ::v8::HandleScope;
65 using ::v8::Local;
66 using ::v8::Message;
69 using ::v8::ObjectTemplate;
70 using ::v8::Persistent;
71 using ::v8::Script;
72 using ::v8::StackTrace;
73 using ::v8::String;
74 using ::v8::TryCatch;
76 using ::v8::UniqueId;
77 using ::v8::V8;
78 using ::v8::Value;
79 
80 
81 #define THREADED_PROFILED_TEST(Name) \
82  static void Test##Name(); \
83  TEST(Name##WithProfiler) { \
84  RunWithProfiler(&Test##Name); \
85  } \
86  THREADED_TEST(Name)
87 
88 
89 void RunWithProfiler(void (*test)()) {
90  LocalContext env;
91  v8::HandleScope scope(env->GetIsolate());
92  v8::Local<v8::String> profile_name =
93  v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
94  v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
95 
96  cpu_profiler->StartCpuProfiling(profile_name);
97  (*test)();
98  reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
99 }
100 
101 
102 static void ExpectString(const char* code, const char* expected) {
103  Local<Value> result = CompileRun(code);
104  CHECK(result->IsString());
105  String::Utf8Value utf8(result);
106  CHECK_EQ(expected, *utf8);
107 }
108 
109 
110 static void ExpectInt32(const char* code, int expected) {
111  Local<Value> result = CompileRun(code);
112  CHECK(result->IsInt32());
113  CHECK_EQ(expected, result->Int32Value());
114 }
115 
116 
117 static void ExpectBoolean(const char* code, bool expected) {
118  Local<Value> result = CompileRun(code);
119  CHECK(result->IsBoolean());
120  CHECK_EQ(expected, result->BooleanValue());
121 }
122 
123 
124 static void ExpectTrue(const char* code) {
125  ExpectBoolean(code, true);
126 }
127 
128 
129 static void ExpectFalse(const char* code) {
130  ExpectBoolean(code, false);
131 }
132 
133 
134 static void ExpectObject(const char* code, Local<Value> expected) {
135  Local<Value> result = CompileRun(code);
136  CHECK(result->Equals(expected));
137 }
138 
139 
140 static void ExpectUndefined(const char* code) {
141  Local<Value> result = CompileRun(code);
142  CHECK(result->IsUndefined());
143 }
144 
145 
146 static int signature_callback_count;
147 static Local<Value> signature_expected_receiver;
148 static void IncrementingSignatureCallback(
151  signature_callback_count++;
152  CHECK_EQ(signature_expected_receiver, args.Holder());
153  CHECK_EQ(signature_expected_receiver, args.This());
154  v8::Handle<v8::Array> result =
155  v8::Array::New(args.GetIsolate(), args.Length());
156  for (int i = 0; i < args.Length(); i++)
157  result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
158  args.GetReturnValue().Set(result);
159 }
160 
161 
162 static void SignatureCallback(
165  v8::Handle<v8::Array> result =
166  v8::Array::New(args.GetIsolate(), args.Length());
167  for (int i = 0; i < args.Length(); i++) {
168  result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
169  }
170  args.GetReturnValue().Set(result);
171 }
172 
173 
174 // Tests that call v8::V8::Dispose() cannot be threaded.
175 TEST(InitializeAndDisposeOnce) {
178 }
179 
180 
181 // Tests that call v8::V8::Dispose() cannot be threaded.
182 TEST(InitializeAndDisposeMultiple) {
183  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
184  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
185  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
186  // TODO(mstarzinger): This should fail gracefully instead of asserting.
187  // for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
188  for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
189 }
190 
191 
192 THREADED_TEST(Handles) {
194  Local<Context> local_env;
195  {
196  LocalContext env;
197  local_env = env.local();
198  }
199 
200  // Local context should still be live.
201  CHECK(!local_env.IsEmpty());
202  local_env->Enter();
203 
205  CHECK(!undef.IsEmpty());
206  CHECK(undef->IsUndefined());
207 
208  const char* source = "1 + 2 + 3";
209  Local<Script> script = v8_compile(source);
210  CHECK_EQ(6, script->Run()->Int32Value());
211 
212  local_env->Exit();
213 }
214 
215 
216 THREADED_TEST(IsolateOfContext) {
218  v8::Handle<Context> env = Context::New(CcTest::isolate());
219 
220  CHECK(!env->GetIsolate()->InContext());
221  CHECK(env->GetIsolate() == CcTest::isolate());
222  env->Enter();
223  CHECK(env->GetIsolate()->InContext());
224  CHECK(env->GetIsolate() == CcTest::isolate());
225  env->Exit();
226  CHECK(!env->GetIsolate()->InContext());
227  CHECK(env->GetIsolate() == CcTest::isolate());
228 }
229 
230 
231 static void TestSignature(const char* loop_js, Local<Value> receiver) {
232  i::ScopedVector<char> source(200);
233  i::OS::SNPrintF(source,
234  "for (var i = 0; i < 10; i++) {"
235  " %s"
236  "}",
237  loop_js);
238  signature_callback_count = 0;
239  signature_expected_receiver = receiver;
240  bool expected_to_throw = receiver.IsEmpty();
241  v8::TryCatch try_catch;
242  CompileRun(source.start());
243  CHECK_EQ(expected_to_throw, try_catch.HasCaught());
244  if (!expected_to_throw) {
245  CHECK_EQ(10, signature_callback_count);
246  } else {
247  CHECK_EQ(v8_str("TypeError: Illegal invocation"),
248  try_catch.Exception()->ToString());
249  }
250 }
251 
252 
253 THREADED_TEST(ReceiverSignature) {
254  LocalContext env;
255  v8::Isolate* isolate = env->GetIsolate();
256  v8::HandleScope scope(isolate);
257  // Setup templates.
259  v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
260  v8::Handle<v8::FunctionTemplate> callback_sig =
262  isolate, IncrementingSignatureCallback, Local<Value>(), sig);
264  v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
266  sub_fun->Inherit(fun);
268  v8::FunctionTemplate::New(isolate);
269  // Install properties.
271  fun_proto->Set(v8_str("prop_sig"), callback_sig);
272  fun_proto->Set(v8_str("prop"), callback);
273  fun_proto->SetAccessorProperty(
274  v8_str("accessor_sig"), callback_sig, callback_sig);
275  fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
276  // Instantiate templates.
277  Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
278  Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
279  // Setup global variables.
280  env->Global()->Set(v8_str("Fun"), fun->GetFunction());
281  env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
282  env->Global()->Set(v8_str("fun_instance"), fun_instance);
283  env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
284  CompileRun(
285  "var accessor_sig_key = 'accessor_sig';"
286  "var accessor_key = 'accessor';"
287  "var prop_sig_key = 'prop_sig';"
288  "var prop_key = 'prop';"
289  ""
290  "function copy_props(obj) {"
291  " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
292  " var source = Fun.prototype;"
293  " for (var i in keys) {"
294  " var key = keys[i];"
295  " var desc = Object.getOwnPropertyDescriptor(source, key);"
296  " Object.defineProperty(obj, key, desc);"
297  " }"
298  "}"
299  ""
300  "var obj = {};"
301  "copy_props(obj);"
302  "var unrel = new UnrelFun();"
303  "copy_props(unrel);");
304  // Test with and without ICs
305  const char* test_objects[] = {
306  "fun_instance", "sub_fun_instance", "obj", "unrel" };
307  unsigned bad_signature_start_offset = 2;
308  for (unsigned i = 0; i < ARRAY_SIZE(test_objects); i++) {
309  i::ScopedVector<char> source(200);
311  source, "var test_object = %s; test_object", test_objects[i]);
312  Local<Value> test_object = CompileRun(source.start());
313  TestSignature("test_object.prop();", test_object);
314  TestSignature("test_object.accessor;", test_object);
315  TestSignature("test_object[accessor_key];", test_object);
316  TestSignature("test_object.accessor = 1;", test_object);
317  TestSignature("test_object[accessor_key] = 1;", test_object);
318  if (i >= bad_signature_start_offset) test_object = Local<Value>();
319  TestSignature("test_object.prop_sig();", test_object);
320  TestSignature("test_object.accessor_sig;", test_object);
321  TestSignature("test_object[accessor_sig_key];", test_object);
322  TestSignature("test_object.accessor_sig = 1;", test_object);
323  TestSignature("test_object[accessor_sig_key] = 1;", test_object);
324  }
325 }
326 
327 
328 THREADED_TEST(ArgumentSignature) {
329  LocalContext env;
330  v8::Isolate* isolate = env->GetIsolate();
331  v8::HandleScope scope(isolate);
333  cons->SetClassName(v8_str("Cons"));
335  isolate, v8::Handle<v8::FunctionTemplate>(), 1, &cons);
338  SignatureCallback,
340  sig);
341  env->Global()->Set(v8_str("Cons"), cons->GetFunction());
342  env->Global()->Set(v8_str("Fun1"), fun->GetFunction());
343 
344  v8::Handle<Value> value1 = CompileRun("Fun1(4) == '';");
345  CHECK(value1->IsTrue());
346 
347  v8::Handle<Value> value2 = CompileRun("Fun1(new Cons()) == '[object Cons]';");
348  CHECK(value2->IsTrue());
349 
350  v8::Handle<Value> value3 = CompileRun("Fun1() == '';");
351  CHECK(value3->IsTrue());
352 
354  cons1->SetClassName(v8_str("Cons1"));
356  cons2->SetClassName(v8_str("Cons2"));
358  cons3->SetClassName(v8_str("Cons3"));
359 
360  v8::Handle<v8::FunctionTemplate> args[3] = { cons1, cons2, cons3 };
362  isolate, v8::Handle<v8::FunctionTemplate>(), 3, args);
365  SignatureCallback,
367  wsig);
368 
369  env->Global()->Set(v8_str("Cons1"), cons1->GetFunction());
370  env->Global()->Set(v8_str("Cons2"), cons2->GetFunction());
371  env->Global()->Set(v8_str("Cons3"), cons3->GetFunction());
372  env->Global()->Set(v8_str("Fun2"), fun2->GetFunction());
373  v8::Handle<Value> value4 = CompileRun(
374  "Fun2(new Cons1(), new Cons2(), new Cons3()) =="
375  "'[object Cons1],[object Cons2],[object Cons3]'");
376  CHECK(value4->IsTrue());
377 
378  v8::Handle<Value> value5 = CompileRun(
379  "Fun2(new Cons1(), new Cons2(), 5) == '[object Cons1],[object Cons2],'");
380  CHECK(value5->IsTrue());
381 
382  v8::Handle<Value> value6 = CompileRun(
383  "Fun2(new Cons3(), new Cons2(), new Cons1()) == ',[object Cons2],'");
384  CHECK(value6->IsTrue());
385 
386  v8::Handle<Value> value7 = CompileRun(
387  "Fun2(new Cons1(), new Cons2(), new Cons3(), 'd') == "
388  "'[object Cons1],[object Cons2],[object Cons3],d';");
389  CHECK(value7->IsTrue());
390 
391  v8::Handle<Value> value8 = CompileRun(
392  "Fun2(new Cons1(), new Cons2()) == '[object Cons1],[object Cons2]'");
393  CHECK(value8->IsTrue());
394 }
395 
396 
397 THREADED_TEST(HulIgennem) {
398  LocalContext env;
399  v8::Isolate* isolate = env->GetIsolate();
400  v8::HandleScope scope(isolate);
401  v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
402  Local<String> undef_str = undef->ToString();
403  char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
404  undef_str->WriteUtf8(value);
405  CHECK_EQ(0, strcmp(value, "undefined"));
406  i::DeleteArray(value);
407 }
408 
409 
410 THREADED_TEST(Access) {
411  LocalContext env;
412  v8::Isolate* isolate = env->GetIsolate();
413  v8::HandleScope scope(isolate);
414  Local<v8::Object> obj = v8::Object::New(isolate);
415  Local<Value> foo_before = obj->Get(v8_str("foo"));
416  CHECK(foo_before->IsUndefined());
417  Local<String> bar_str = v8_str("bar");
418  obj->Set(v8_str("foo"), bar_str);
419  Local<Value> foo_after = obj->Get(v8_str("foo"));
420  CHECK(!foo_after->IsUndefined());
421  CHECK(foo_after->IsString());
422  CHECK_EQ(bar_str, foo_after);
423 }
424 
425 
426 THREADED_TEST(AccessElement) {
427  LocalContext env;
428  v8::HandleScope scope(env->GetIsolate());
429  Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
430  Local<Value> before = obj->Get(1);
431  CHECK(before->IsUndefined());
432  Local<String> bar_str = v8_str("bar");
433  obj->Set(1, bar_str);
434  Local<Value> after = obj->Get(1);
435  CHECK(!after->IsUndefined());
436  CHECK(after->IsString());
437  CHECK_EQ(bar_str, after);
438 
439  Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
440  CHECK_EQ(v8_str("a"), value->Get(0));
441  CHECK_EQ(v8_str("b"), value->Get(1));
442 }
443 
444 
445 THREADED_TEST(Script) {
446  LocalContext env;
447  v8::HandleScope scope(env->GetIsolate());
448  const char* source = "1 + 2 + 3";
449  Local<Script> script = v8_compile(source);
450  CHECK_EQ(6, script->Run()->Int32Value());
451 }
452 
453 
454 static uint16_t* AsciiToTwoByteString(const char* source) {
455  int array_length = i::StrLength(source) + 1;
456  uint16_t* converted = i::NewArray<uint16_t>(array_length);
457  for (int i = 0; i < array_length; i++) converted[i] = source[i];
458  return converted;
459 }
460 
461 
462 class TestResource: public String::ExternalStringResource {
463  public:
464  TestResource(uint16_t* data, int* counter = NULL, bool owning_data = true)
465  : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
466  while (data[length_]) ++length_;
467  }
468 
470  if (owning_data_) i::DeleteArray(data_);
471  if (counter_ != NULL) ++*counter_;
472  }
473 
474  const uint16_t* data() const {
475  return data_;
476  }
477 
478  size_t length() const {
479  return length_;
480  }
481 
482  private:
483  uint16_t* data_;
484  size_t length_;
485  int* counter_;
486  bool owning_data_;
487 };
488 
489 
490 class TestAsciiResource: public String::ExternalAsciiStringResource {
491  public:
492  TestAsciiResource(const char* data, int* counter = NULL, size_t offset = 0)
493  : orig_data_(data),
494  data_(data + offset),
495  length_(strlen(data) - offset),
496  counter_(counter) { }
497 
499  i::DeleteArray(orig_data_);
500  if (counter_ != NULL) ++*counter_;
501  }
502 
503  const char* data() const {
504  return data_;
505  }
506 
507  size_t length() const {
508  return length_;
509  }
510 
511  private:
512  const char* orig_data_;
513  const char* data_;
514  size_t length_;
515  int* counter_;
516 };
517 
518 
519 THREADED_TEST(ScriptUsingStringResource) {
520  int dispose_count = 0;
521  const char* c_source = "1 + 2 * 3";
522  uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
523  {
524  LocalContext env;
525  v8::HandleScope scope(env->GetIsolate());
526  TestResource* resource = new TestResource(two_byte_source, &dispose_count);
527  Local<String> source = String::NewExternal(env->GetIsolate(), resource);
528  Local<Script> script = v8_compile(source);
529  Local<Value> value = script->Run();
530  CHECK(value->IsNumber());
531  CHECK_EQ(7, value->Int32Value());
532  CHECK(source->IsExternal());
533  CHECK_EQ(resource,
534  static_cast<TestResource*>(source->GetExternalStringResource()));
535  String::Encoding encoding = String::UNKNOWN_ENCODING;
536  CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
537  source->GetExternalStringResourceBase(&encoding));
538  CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
540  CHECK_EQ(0, dispose_count);
541  }
544  CHECK_EQ(1, dispose_count);
545 }
546 
547 
548 THREADED_TEST(ScriptUsingAsciiStringResource) {
549  int dispose_count = 0;
550  const char* c_source = "1 + 2 * 3";
551  {
552  LocalContext env;
553  v8::HandleScope scope(env->GetIsolate());
554  TestAsciiResource* resource = new TestAsciiResource(i::StrDup(c_source),
555  &dispose_count);
556  Local<String> source = String::NewExternal(env->GetIsolate(), resource);
557  CHECK(source->IsExternalAscii());
558  CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
559  source->GetExternalAsciiStringResource());
560  String::Encoding encoding = String::UNKNOWN_ENCODING;
561  CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
562  source->GetExternalStringResourceBase(&encoding));
563  CHECK_EQ(String::ASCII_ENCODING, encoding);
564  Local<Script> script = v8_compile(source);
565  Local<Value> value = script->Run();
566  CHECK(value->IsNumber());
567  CHECK_EQ(7, value->Int32Value());
569  CHECK_EQ(0, dispose_count);
570  }
573  CHECK_EQ(1, dispose_count);
574 }
575 
576 
577 THREADED_TEST(ScriptMakingExternalString) {
578  int dispose_count = 0;
579  uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
580  {
581  LocalContext env;
582  v8::HandleScope scope(env->GetIsolate());
583  Local<String> source =
584  String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
585  // Trigger GCs so that the newly allocated string moves to old gen.
586  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
587  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
588  CHECK_EQ(source->IsExternal(), false);
589  CHECK_EQ(source->IsExternalAscii(), false);
590  String::Encoding encoding = String::UNKNOWN_ENCODING;
591  CHECK_EQ(NULL, source->GetExternalStringResourceBase(&encoding));
592  CHECK_EQ(String::ASCII_ENCODING, encoding);
593  bool success = source->MakeExternal(new TestResource(two_byte_source,
594  &dispose_count));
595  CHECK(success);
596  Local<Script> script = v8_compile(source);
597  Local<Value> value = script->Run();
598  CHECK(value->IsNumber());
599  CHECK_EQ(7, value->Int32Value());
601  CHECK_EQ(0, dispose_count);
602  }
605  CHECK_EQ(1, dispose_count);
606 }
607 
608 
609 THREADED_TEST(ScriptMakingExternalAsciiString) {
610  int dispose_count = 0;
611  const char* c_source = "1 + 2 * 3";
612  {
613  LocalContext env;
614  v8::HandleScope scope(env->GetIsolate());
615  Local<String> source = v8_str(c_source);
616  // Trigger GCs so that the newly allocated string moves to old gen.
617  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
618  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
619  bool success = source->MakeExternal(
620  new TestAsciiResource(i::StrDup(c_source), &dispose_count));
621  CHECK(success);
622  Local<Script> script = v8_compile(source);
623  Local<Value> value = script->Run();
624  CHECK(value->IsNumber());
625  CHECK_EQ(7, value->Int32Value());
627  CHECK_EQ(0, dispose_count);
628  }
631  CHECK_EQ(1, dispose_count);
632 }
633 
634 
635 TEST(MakingExternalStringConditions) {
636  LocalContext env;
637  v8::HandleScope scope(env->GetIsolate());
638 
639  // Free some space in the new space so that we can check freshness.
642 
643  uint16_t* two_byte_string = AsciiToTwoByteString("s1");
644  Local<String> small_string =
645  String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
646  i::DeleteArray(two_byte_string);
647 
648  // We should refuse to externalize newly created small string.
649  CHECK(!small_string->CanMakeExternal());
650  // Trigger GCs so that the newly allocated string moves to old gen.
651  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
652  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
653  // Old space strings should be accepted.
654  CHECK(small_string->CanMakeExternal());
655 
656  two_byte_string = AsciiToTwoByteString("small string 2");
657  small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
658  i::DeleteArray(two_byte_string);
659 
660  // We should refuse externalizing newly created small string.
661  CHECK(!small_string->CanMakeExternal());
662  for (int i = 0; i < 100; i++) {
663  String::Value value(small_string);
664  }
665  // Frequently used strings should be accepted.
666  CHECK(small_string->CanMakeExternal());
667 
668  const int buf_size = 10 * 1024;
669  char* buf = i::NewArray<char>(buf_size);
670  memset(buf, 'a', buf_size);
671  buf[buf_size - 1] = '\0';
672 
673  two_byte_string = AsciiToTwoByteString(buf);
674  Local<String> large_string =
675  String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
676  i::DeleteArray(buf);
677  i::DeleteArray(two_byte_string);
678  // Large strings should be immediately accepted.
679  CHECK(large_string->CanMakeExternal());
680 }
681 
682 
683 TEST(MakingExternalAsciiStringConditions) {
684  LocalContext env;
685  v8::HandleScope scope(env->GetIsolate());
686 
687  // Free some space in the new space so that we can check freshness.
690 
691  Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
692  // We should refuse to externalize newly created small string.
693  CHECK(!small_string->CanMakeExternal());
694  // Trigger GCs so that the newly allocated string moves to old gen.
695  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
696  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
697  // Old space strings should be accepted.
698  CHECK(small_string->CanMakeExternal());
699 
700  small_string = String::NewFromUtf8(env->GetIsolate(), "small string 2");
701  // We should refuse externalizing newly created small string.
702  CHECK(!small_string->CanMakeExternal());
703  for (int i = 0; i < 100; i++) {
704  String::Value value(small_string);
705  }
706  // Frequently used strings should be accepted.
707  CHECK(small_string->CanMakeExternal());
708 
709  const int buf_size = 10 * 1024;
710  char* buf = i::NewArray<char>(buf_size);
711  memset(buf, 'a', buf_size);
712  buf[buf_size - 1] = '\0';
713  Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
714  i::DeleteArray(buf);
715  // Large strings should be immediately accepted.
716  CHECK(large_string->CanMakeExternal());
717 }
718 
719 
720 TEST(MakingExternalUnalignedAsciiString) {
721  LocalContext env;
722  v8::HandleScope scope(env->GetIsolate());
723 
724  CompileRun("function cons(a, b) { return a + b; }"
725  "function slice(a) { return a.substring(1); }");
726  // Create a cons string that will land in old pointer space.
727  Local<String> cons = Local<String>::Cast(CompileRun(
728  "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
729  // Create a sliced string that will land in old pointer space.
730  Local<String> slice = Local<String>::Cast(CompileRun(
731  "slice('abcdefghijklmnopqrstuvwxyz');"));
732 
733  // Trigger GCs so that the newly allocated string moves to old gen.
734  SimulateFullSpace(CcTest::heap()->old_pointer_space());
735  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
736  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
737 
738  // Turn into external string with unaligned resource data.
739  const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
740  bool success = cons->MakeExternal(
741  new TestAsciiResource(i::StrDup(c_cons), NULL, 1));
742  CHECK(success);
743  const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
744  success = slice->MakeExternal(
745  new TestAsciiResource(i::StrDup(c_slice), NULL, 1));
746  CHECK(success);
747 
748  // Trigger GCs and force evacuation.
751 }
752 
753 
754 THREADED_TEST(UsingExternalString) {
755  i::Factory* factory = CcTest::i_isolate()->factory();
756  {
758  uint16_t* two_byte_string = AsciiToTwoByteString("test string");
759  Local<String> string = String::NewExternal(
760  CcTest::isolate(), new TestResource(two_byte_string));
761  i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
762  // Trigger GCs so that the newly allocated string moves to old gen.
763  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
764  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
765  i::Handle<i::String> isymbol =
766  factory->InternalizeString(istring);
767  CHECK(isymbol->IsInternalizedString());
768  }
771 }
772 
773 
774 THREADED_TEST(UsingExternalAsciiString) {
775  i::Factory* factory = CcTest::i_isolate()->factory();
776  {
778  const char* one_byte_string = "test string";
779  Local<String> string = String::NewExternal(
780  CcTest::isolate(), new TestAsciiResource(i::StrDup(one_byte_string)));
781  i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
782  // Trigger GCs so that the newly allocated string moves to old gen.
783  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
784  CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
785  i::Handle<i::String> isymbol =
786  factory->InternalizeString(istring);
787  CHECK(isymbol->IsInternalizedString());
788  }
791 }
792 
793 
794 THREADED_TEST(ScavengeExternalString) {
795  i::FLAG_stress_compaction = false;
796  i::FLAG_gc_global = false;
797  int dispose_count = 0;
798  bool in_new_space = false;
799  {
801  uint16_t* two_byte_string = AsciiToTwoByteString("test string");
802  Local<String> string = String::NewExternal(
803  CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
804  i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
806  in_new_space = CcTest::heap()->InNewSpace(*istring);
807  CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
808  CHECK_EQ(0, dispose_count);
809  }
811  in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
812  CHECK_EQ(1, dispose_count);
813 }
814 
815 
816 THREADED_TEST(ScavengeExternalAsciiString) {
817  i::FLAG_stress_compaction = false;
818  i::FLAG_gc_global = false;
819  int dispose_count = 0;
820  bool in_new_space = false;
821  {
823  const char* one_byte_string = "test string";
824  Local<String> string = String::NewExternal(
825  CcTest::isolate(),
826  new TestAsciiResource(i::StrDup(one_byte_string), &dispose_count));
827  i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
829  in_new_space = CcTest::heap()->InNewSpace(*istring);
830  CHECK(in_new_space || CcTest::heap()->old_data_space()->Contains(*istring));
831  CHECK_EQ(0, dispose_count);
832  }
834  in_new_space ? i::NEW_SPACE : i::OLD_DATA_SPACE);
835  CHECK_EQ(1, dispose_count);
836 }
837 
838 
840  public:
841  // Only used by non-threaded tests, so it can use static fields.
842  static int dispose_calls;
843  static int dispose_count;
844 
845  TestAsciiResourceWithDisposeControl(const char* data, bool dispose)
847  dispose_(dispose) { }
848 
849  void Dispose() {
850  ++dispose_calls;
851  if (dispose_) delete this;
852  }
853  private:
854  bool dispose_;
855 };
856 
857 
860 
861 
862 TEST(ExternalStringWithDisposeHandling) {
863  const char* c_source = "1 + 2 * 3";
864 
865  // Use a stack allocated external string resource allocated object.
866  TestAsciiResourceWithDisposeControl::dispose_count = 0;
867  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
868  TestAsciiResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
869  {
870  LocalContext env;
871  v8::HandleScope scope(env->GetIsolate());
872  Local<String> source = String::NewExternal(env->GetIsolate(), &res_stack);
873  Local<Script> script = v8_compile(source);
874  Local<Value> value = script->Run();
875  CHECK(value->IsNumber());
876  CHECK_EQ(7, value->Int32Value());
878  CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
879  }
882  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
883  CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
884 
885  // Use a heap allocated external string resource allocated object.
886  TestAsciiResourceWithDisposeControl::dispose_count = 0;
887  TestAsciiResourceWithDisposeControl::dispose_calls = 0;
888  TestAsciiResource* res_heap =
889  new TestAsciiResourceWithDisposeControl(i::StrDup(c_source), true);
890  {
891  LocalContext env;
892  v8::HandleScope scope(env->GetIsolate());
893  Local<String> source = String::NewExternal(env->GetIsolate(), res_heap);
894  Local<Script> script = v8_compile(source);
895  Local<Value> value = script->Run();
896  CHECK(value->IsNumber());
897  CHECK_EQ(7, value->Int32Value());
899  CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
900  }
903  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
904  CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
905 }
906 
907 
908 THREADED_TEST(StringConcat) {
909  {
910  LocalContext env;
911  v8::HandleScope scope(env->GetIsolate());
912  const char* one_byte_string_1 = "function a_times_t";
913  const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
914  const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
915  const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
916  const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
917  const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
918  const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
919  Local<String> left = v8_str(one_byte_string_1);
920 
921  uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
922  Local<String> right =
923  String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
924  i::DeleteArray(two_byte_source);
925 
926  Local<String> source = String::Concat(left, right);
927  right = String::NewExternal(
928  env->GetIsolate(), new TestAsciiResource(i::StrDup(one_byte_extern_1)));
929  source = String::Concat(source, right);
930  right = String::NewExternal(
931  env->GetIsolate(),
932  new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
933  source = String::Concat(source, right);
934  right = v8_str(one_byte_string_2);
935  source = String::Concat(source, right);
936 
937  two_byte_source = AsciiToTwoByteString(two_byte_string_2);
938  right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
939  i::DeleteArray(two_byte_source);
940 
941  source = String::Concat(source, right);
942  right = String::NewExternal(
943  env->GetIsolate(),
944  new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
945  source = String::Concat(source, right);
946  Local<Script> script = v8_compile(source);
947  Local<Value> value = script->Run();
948  CHECK(value->IsNumber());
949  CHECK_EQ(68, value->Int32Value());
950  }
954 }
955 
956 
957 THREADED_TEST(GlobalProperties) {
958  LocalContext env;
959  v8::HandleScope scope(env->GetIsolate());
960  v8::Handle<v8::Object> global = env->Global();
961  global->Set(v8_str("pi"), v8_num(3.1415926));
962  Local<Value> pi = global->Get(v8_str("pi"));
963  CHECK_EQ(3.1415926, pi->NumberValue());
964 }
965 
966 
967 template<typename T>
968 static void CheckReturnValue(const T& t, i::Address callback) {
969  v8::ReturnValue<v8::Value> rv = t.GetReturnValue();
970  i::Object** o = *reinterpret_cast<i::Object***>(&rv);
971  CHECK_EQ(CcTest::isolate(), t.GetIsolate());
972  CHECK_EQ(t.GetIsolate(), rv.GetIsolate());
973  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
974  // Verify reset
975  bool is_runtime = (*o)->IsTheHole();
976  rv.Set(true);
977  CHECK(!(*o)->IsTheHole() && !(*o)->IsUndefined());
979  CHECK((*o)->IsTheHole() || (*o)->IsUndefined());
980  CHECK_EQ(is_runtime, (*o)->IsTheHole());
981 
982  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(t.GetIsolate());
983  // If CPU profiler is active check that when API callback is invoked
984  // VMState is set to EXTERNAL.
985  if (isolate->cpu_profiler()->is_profiling()) {
986  CHECK_EQ(i::EXTERNAL, isolate->current_vm_state());
987  CHECK(isolate->external_callback_scope());
988  CHECK_EQ(callback, isolate->external_callback_scope()->callback());
989  }
990 }
991 
992 
993 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
994  i::Address callback) {
996  CheckReturnValue(info, callback);
997  info.GetReturnValue().Set(v8_str("bad value"));
998  info.GetReturnValue().Set(v8_num(102));
999 }
1000 
1001 
1002 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
1003  return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
1004 }
1005 
1006 
1007 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
1008  return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
1009 }
1010 
1011 static void construct_callback(
1012  const v8::FunctionCallbackInfo<Value>& info) {
1014  CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
1015  info.This()->Set(v8_str("x"), v8_num(1));
1016  info.This()->Set(v8_str("y"), v8_num(2));
1017  info.GetReturnValue().Set(v8_str("bad value"));
1018  info.GetReturnValue().Set(info.This());
1019 }
1020 
1021 
1022 static void Return239Callback(
1023  Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
1025  CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
1026  info.GetReturnValue().Set(v8_str("bad value"));
1027  info.GetReturnValue().Set(v8_num(239));
1028 }
1029 
1030 
1031 template<typename Handler>
1032 static void TestFunctionTemplateInitializer(Handler handler,
1033  Handler handler_2) {
1034  // Test constructor calls.
1035  {
1036  LocalContext env;
1037  v8::Isolate* isolate = env->GetIsolate();
1038  v8::HandleScope scope(isolate);
1039 
1040  Local<v8::FunctionTemplate> fun_templ =
1041  v8::FunctionTemplate::New(isolate, handler);
1042  Local<Function> fun = fun_templ->GetFunction();
1043  env->Global()->Set(v8_str("obj"), fun);
1044  Local<Script> script = v8_compile("obj()");
1045  for (int i = 0; i < 30; i++) {
1046  CHECK_EQ(102, script->Run()->Int32Value());
1047  }
1048  }
1049  // Use SetCallHandler to initialize a function template, should work like
1050  // the previous one.
1051  {
1052  LocalContext env;
1053  v8::Isolate* isolate = env->GetIsolate();
1054  v8::HandleScope scope(isolate);
1055 
1056  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
1057  fun_templ->SetCallHandler(handler_2);
1058  Local<Function> fun = fun_templ->GetFunction();
1059  env->Global()->Set(v8_str("obj"), fun);
1060  Local<Script> script = v8_compile("obj()");
1061  for (int i = 0; i < 30; i++) {
1062  CHECK_EQ(102, script->Run()->Int32Value());
1063  }
1064  }
1065 }
1066 
1067 
1068 template<typename Constructor, typename Accessor>
1069 static void TestFunctionTemplateAccessor(Constructor constructor,
1070  Accessor accessor) {
1071  LocalContext env;
1072  v8::HandleScope scope(env->GetIsolate());
1073 
1074  Local<v8::FunctionTemplate> fun_templ =
1075  v8::FunctionTemplate::New(env->GetIsolate(), constructor);
1076  fun_templ->SetClassName(v8_str("funky"));
1077  fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
1078  Local<Function> fun = fun_templ->GetFunction();
1079  env->Global()->Set(v8_str("obj"), fun);
1080  Local<Value> result = v8_compile("(new obj()).toString()")->Run();
1081  CHECK_EQ(v8_str("[object funky]"), result);
1082  CompileRun("var obj_instance = new obj();");
1083  Local<Script> script;
1084  script = v8_compile("obj_instance.x");
1085  for (int i = 0; i < 30; i++) {
1086  CHECK_EQ(1, script->Run()->Int32Value());
1087  }
1088  script = v8_compile("obj_instance.m");
1089  for (int i = 0; i < 30; i++) {
1090  CHECK_EQ(239, script->Run()->Int32Value());
1091  }
1092 }
1093 
1094 
1095 THREADED_PROFILED_TEST(FunctionTemplate) {
1096  TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
1097  TestFunctionTemplateAccessor(construct_callback, Return239Callback);
1098 }
1099 
1100 
1101 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
1103  CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
1104  info.GetReturnValue().Set(v8_num(51423 + info.Length()));
1105 }
1106 
1107 
1108 template<typename Callback>
1109 static void TestSimpleCallback(Callback callback) {
1110  LocalContext env;
1111  v8::Isolate* isolate = env->GetIsolate();
1112  v8::HandleScope scope(isolate);
1113 
1114  v8::Handle<v8::ObjectTemplate> object_template =
1115  v8::ObjectTemplate::New(isolate);
1116  object_template->Set(isolate, "callback",
1117  v8::FunctionTemplate::New(isolate, callback));
1118  v8::Local<v8::Object> object = object_template->NewInstance();
1119  (*env)->Global()->Set(v8_str("callback_object"), object);
1120  v8::Handle<v8::Script> script;
1121  script = v8_compile("callback_object.callback(17)");
1122  for (int i = 0; i < 30; i++) {
1123  CHECK_EQ(51424, script->Run()->Int32Value());
1124  }
1125  script = v8_compile("callback_object.callback(17, 24)");
1126  for (int i = 0; i < 30; i++) {
1127  CHECK_EQ(51425, script->Run()->Int32Value());
1128  }
1129 }
1130 
1131 
1132 THREADED_PROFILED_TEST(SimpleCallback) {
1133  TestSimpleCallback(SimpleCallback);
1134 }
1135 
1136 
1137 template<typename T>
1139 
1140 // constant return values
1141 static int32_t fast_return_value_int32 = 471;
1142 static uint32_t fast_return_value_uint32 = 571;
1143 static const double kFastReturnValueDouble = 2.7;
1144 // variable return values
1145 static bool fast_return_value_bool = false;
1150 };
1151 static ReturnValueOddball fast_return_value_void;
1152 static bool fast_return_value_object_is_empty = false;
1153 
1154 // Helper function to avoid compiler error: insufficient contextual information
1155 // to determine type when applying FUNCTION_ADDR to a template function.
1156 static i::Address address_of(v8::FunctionCallback callback) {
1157  return FUNCTION_ADDR(callback);
1158 }
1159 
1160 template<>
1163  CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1164  info.GetReturnValue().Set(fast_return_value_int32);
1165 }
1166 
1167 template<>
1170  CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1171  info.GetReturnValue().Set(fast_return_value_uint32);
1172 }
1173 
1174 template<>
1177  CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1178  info.GetReturnValue().Set(kFastReturnValueDouble);
1179 }
1180 
1181 template<>
1184  CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1185  info.GetReturnValue().Set(fast_return_value_bool);
1186 }
1187 
1188 template<>
1191  CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1192  switch (fast_return_value_void) {
1193  case kNullReturnValue:
1194  info.GetReturnValue().SetNull();
1195  break;
1196  case kUndefinedReturnValue:
1197  info.GetReturnValue().SetUndefined();
1198  break;
1200  info.GetReturnValue().SetEmptyString();
1201  break;
1202  }
1203 }
1204 
1205 template<>
1208  v8::Handle<v8::Object> object;
1209  if (!fast_return_value_object_is_empty) {
1210  object = Object::New(info.GetIsolate());
1211  }
1212  info.GetReturnValue().Set(object);
1213 }
1214 
1215 template<typename T>
1216 Handle<Value> TestFastReturnValues() {
1217  LocalContext env;
1218  v8::Isolate* isolate = env->GetIsolate();
1219  v8::EscapableHandleScope scope(isolate);
1220  v8::Handle<v8::ObjectTemplate> object_template =
1221  v8::ObjectTemplate::New(isolate);
1222  v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1223  object_template->Set(isolate, "callback",
1224  v8::FunctionTemplate::New(isolate, callback));
1225  v8::Local<v8::Object> object = object_template->NewInstance();
1226  (*env)->Global()->Set(v8_str("callback_object"), object);
1227  return scope.Escape(CompileRun("callback_object.callback()"));
1228 }
1229 
1230 
1231 THREADED_PROFILED_TEST(FastReturnValues) {
1232  LocalContext env;
1234  v8::Handle<v8::Value> value;
1235  // check int32_t and uint32_t
1236  int32_t int_values[] = {
1237  0, 234, -723,
1239  };
1240  for (size_t i = 0; i < ARRAY_SIZE(int_values); i++) {
1241  for (int modifier = -1; modifier <= 1; modifier++) {
1242  int int_value = int_values[i] + modifier;
1243  // check int32_t
1244  fast_return_value_int32 = int_value;
1245  value = TestFastReturnValues<int32_t>();
1246  CHECK(value->IsInt32());
1247  CHECK(fast_return_value_int32 == value->Int32Value());
1248  // check uint32_t
1249  fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1250  value = TestFastReturnValues<uint32_t>();
1251  CHECK(value->IsUint32());
1252  CHECK(fast_return_value_uint32 == value->Uint32Value());
1253  }
1254  }
1255  // check double
1256  value = TestFastReturnValues<double>();
1257  CHECK(value->IsNumber());
1258  CHECK_EQ(kFastReturnValueDouble, value->ToNumber()->Value());
1259  // check bool values
1260  for (int i = 0; i < 2; i++) {
1261  fast_return_value_bool = i == 0;
1262  value = TestFastReturnValues<bool>();
1263  CHECK(value->IsBoolean());
1264  CHECK_EQ(fast_return_value_bool, value->ToBoolean()->Value());
1265  }
1266  // check oddballs
1267  ReturnValueOddball oddballs[] = {
1271  };
1272  for (size_t i = 0; i < ARRAY_SIZE(oddballs); i++) {
1273  fast_return_value_void = oddballs[i];
1274  value = TestFastReturnValues<void>();
1275  switch (fast_return_value_void) {
1276  case kNullReturnValue:
1277  CHECK(value->IsNull());
1278  break;
1279  case kUndefinedReturnValue:
1280  CHECK(value->IsUndefined());
1281  break;
1283  CHECK(value->IsString());
1284  CHECK_EQ(0, v8::String::Cast(*value)->Length());
1285  break;
1286  }
1287  }
1288  // check handles
1289  fast_return_value_object_is_empty = false;
1290  value = TestFastReturnValues<Object>();
1291  CHECK(value->IsObject());
1292  fast_return_value_object_is_empty = true;
1293  value = TestFastReturnValues<Object>();
1294  CHECK(value->IsUndefined());
1295 }
1296 
1297 
1298 THREADED_TEST(FunctionTemplateSetLength) {
1299  LocalContext env;
1300  v8::Isolate* isolate = env->GetIsolate();
1301  v8::HandleScope scope(isolate);
1302  {
1303  Local<v8::FunctionTemplate> fun_templ =
1304  v8::FunctionTemplate::New(isolate,
1305  handle_callback,
1306  Handle<v8::Value>(),
1307  Handle<v8::Signature>(),
1308  23);
1309  Local<Function> fun = fun_templ->GetFunction();
1310  env->Global()->Set(v8_str("obj"), fun);
1311  Local<Script> script = v8_compile("obj.length");
1312  CHECK_EQ(23, script->Run()->Int32Value());
1313  }
1314  {
1315  Local<v8::FunctionTemplate> fun_templ =
1316  v8::FunctionTemplate::New(isolate, handle_callback);
1317  fun_templ->SetLength(22);
1318  Local<Function> fun = fun_templ->GetFunction();
1319  env->Global()->Set(v8_str("obj"), fun);
1320  Local<Script> script = v8_compile("obj.length");
1321  CHECK_EQ(22, script->Run()->Int32Value());
1322  }
1323  {
1324  // Without setting length it defaults to 0.
1325  Local<v8::FunctionTemplate> fun_templ =
1326  v8::FunctionTemplate::New(isolate, handle_callback);
1327  Local<Function> fun = fun_templ->GetFunction();
1328  env->Global()->Set(v8_str("obj"), fun);
1329  Local<Script> script = v8_compile("obj.length");
1330  CHECK_EQ(0, script->Run()->Int32Value());
1331  }
1332 }
1333 
1334 
1335 static void* expected_ptr;
1336 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1337  void* ptr = v8::External::Cast(*args.Data())->Value();
1338  CHECK_EQ(expected_ptr, ptr);
1339  args.GetReturnValue().Set(true);
1340 }
1341 
1342 
1343 static void TestExternalPointerWrapping() {
1344  LocalContext env;
1345  v8::Isolate* isolate = env->GetIsolate();
1346  v8::HandleScope scope(isolate);
1347 
1348  v8::Handle<v8::Value> data =
1349  v8::External::New(isolate, expected_ptr);
1350 
1352  obj->Set(v8_str("func"),
1353  v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
1354  env->Global()->Set(v8_str("obj"), obj);
1355 
1356  CHECK(CompileRun(
1357  "function foo() {\n"
1358  " for (var i = 0; i < 13; i++) obj.func();\n"
1359  "}\n"
1360  "foo(), true")->BooleanValue());
1361 }
1362 
1363 
1364 THREADED_TEST(ExternalWrap) {
1365  // Check heap allocated object.
1366  int* ptr = new int;
1367  expected_ptr = ptr;
1368  TestExternalPointerWrapping();
1369  delete ptr;
1370 
1371  // Check stack allocated object.
1372  int foo;
1373  expected_ptr = &foo;
1374  TestExternalPointerWrapping();
1375 
1376  // Check not aligned addresses.
1377  const int n = 100;
1378  char* s = new char[n];
1379  for (int i = 0; i < n; i++) {
1380  expected_ptr = s + i;
1381  TestExternalPointerWrapping();
1382  }
1383 
1384  delete[] s;
1385 
1386  // Check several invalid addresses.
1387  expected_ptr = reinterpret_cast<void*>(1);
1388  TestExternalPointerWrapping();
1389 
1390  expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1391  TestExternalPointerWrapping();
1392 
1393  expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1394  TestExternalPointerWrapping();
1395 
1396 #if defined(V8_HOST_ARCH_X64)
1397  // Check a value with a leading 1 bit in x64 Smi encoding.
1398  expected_ptr = reinterpret_cast<void*>(0x400000000);
1399  TestExternalPointerWrapping();
1400 
1401  expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1402  TestExternalPointerWrapping();
1403 
1404  expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1405  TestExternalPointerWrapping();
1406 #endif
1407 }
1408 
1409 
1410 THREADED_TEST(FindInstanceInPrototypeChain) {
1411  LocalContext env;
1412  v8::Isolate* isolate = env->GetIsolate();
1413  v8::HandleScope scope(isolate);
1414 
1415  Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1416  Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1417  Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
1418  derived->Inherit(base);
1419 
1420  Local<v8::Function> base_function = base->GetFunction();
1421  Local<v8::Function> derived_function = derived->GetFunction();
1422  Local<v8::Function> other_function = other->GetFunction();
1423 
1424  Local<v8::Object> base_instance = base_function->NewInstance();
1425  Local<v8::Object> derived_instance = derived_function->NewInstance();
1426  Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1427  Local<v8::Object> other_instance = other_function->NewInstance();
1428  derived_instance2->Set(v8_str("__proto__"), derived_instance);
1429  other_instance->Set(v8_str("__proto__"), derived_instance2);
1430 
1431  // base_instance is only an instance of base.
1432  CHECK_EQ(base_instance,
1433  base_instance->FindInstanceInPrototypeChain(base));
1434  CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1435  CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1436 
1437  // derived_instance is an instance of base and derived.
1438  CHECK_EQ(derived_instance,
1439  derived_instance->FindInstanceInPrototypeChain(base));
1440  CHECK_EQ(derived_instance,
1441  derived_instance->FindInstanceInPrototypeChain(derived));
1442  CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1443 
1444  // other_instance is an instance of other and its immediate
1445  // prototype derived_instance2 is an instance of base and derived.
1446  // Note, derived_instance is an instance of base and derived too,
1447  // but it comes after derived_instance2 in the prototype chain of
1448  // other_instance.
1449  CHECK_EQ(derived_instance2,
1450  other_instance->FindInstanceInPrototypeChain(base));
1451  CHECK_EQ(derived_instance2,
1452  other_instance->FindInstanceInPrototypeChain(derived));
1453  CHECK_EQ(other_instance,
1454  other_instance->FindInstanceInPrototypeChain(other));
1455 }
1456 
1457 
1458 THREADED_TEST(TinyInteger) {
1459  LocalContext env;
1460  v8::Isolate* isolate = env->GetIsolate();
1461  v8::HandleScope scope(isolate);
1462 
1463  int32_t value = 239;
1464  Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1465  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1466 
1467  value_obj = v8::Integer::New(isolate, value);
1468  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1469 }
1470 
1471 
1472 THREADED_TEST(BigSmiInteger) {
1473  LocalContext env;
1474  v8::HandleScope scope(env->GetIsolate());
1475  v8::Isolate* isolate = CcTest::isolate();
1476 
1477  int32_t value = i::Smi::kMaxValue;
1478  // We cannot add one to a Smi::kMaxValue without wrapping.
1479  if (i::SmiValuesAre31Bits()) {
1480  CHECK(i::Smi::IsValid(value));
1481  CHECK(!i::Smi::IsValid(value + 1));
1482 
1483  Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1484  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1485 
1486  value_obj = v8::Integer::New(isolate, value);
1487  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1488  }
1489 }
1490 
1491 
1492 THREADED_TEST(BigInteger) {
1493  LocalContext env;
1494  v8::HandleScope scope(env->GetIsolate());
1495  v8::Isolate* isolate = CcTest::isolate();
1496 
1497  // We cannot add one to a Smi::kMaxValue without wrapping.
1498  if (i::SmiValuesAre31Bits()) {
1499  // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1500  // The code will not be run in that case, due to the "if" guard.
1501  int32_t value =
1502  static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1503  CHECK(value > i::Smi::kMaxValue);
1504  CHECK(!i::Smi::IsValid(value));
1505 
1506  Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1507  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1508 
1509  value_obj = v8::Integer::New(isolate, value);
1510  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1511  }
1512 }
1513 
1514 
1515 THREADED_TEST(TinyUnsignedInteger) {
1516  LocalContext env;
1517  v8::HandleScope scope(env->GetIsolate());
1518  v8::Isolate* isolate = CcTest::isolate();
1519 
1520  uint32_t value = 239;
1521 
1522  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1523  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1524 
1525  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1526  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1527 }
1528 
1529 
1530 THREADED_TEST(BigUnsignedSmiInteger) {
1531  LocalContext env;
1532  v8::HandleScope scope(env->GetIsolate());
1533  v8::Isolate* isolate = CcTest::isolate();
1534 
1535  uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1536  CHECK(i::Smi::IsValid(value));
1537  CHECK(!i::Smi::IsValid(value + 1));
1538 
1539  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1540  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1541 
1542  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1543  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1544 }
1545 
1546 
1547 THREADED_TEST(BigUnsignedInteger) {
1548  LocalContext env;
1549  v8::HandleScope scope(env->GetIsolate());
1550  v8::Isolate* isolate = CcTest::isolate();
1551 
1552  uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1553  CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1554  CHECK(!i::Smi::IsValid(value));
1555 
1556  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1557  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1558 
1559  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1560  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1561 }
1562 
1563 
1564 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
1565  LocalContext env;
1566  v8::HandleScope scope(env->GetIsolate());
1567  v8::Isolate* isolate = CcTest::isolate();
1568 
1569  uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1570  uint32_t value = INT32_MAX_AS_UINT + 1;
1571  CHECK(value > INT32_MAX_AS_UINT); // No overflow.
1572 
1573  Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1574  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1575 
1576  value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1577  CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1578 }
1579 
1580 
1581 THREADED_TEST(IsNativeError) {
1582  LocalContext env;
1583  v8::HandleScope scope(env->GetIsolate());
1584  v8::Handle<Value> syntax_error = CompileRun(
1585  "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1586  CHECK(syntax_error->IsNativeError());
1587  v8::Handle<Value> not_error = CompileRun("{a:42}");
1588  CHECK(!not_error->IsNativeError());
1589  v8::Handle<Value> not_object = CompileRun("42");
1590  CHECK(!not_object->IsNativeError());
1591 }
1592 
1593 
1594 THREADED_TEST(StringObject) {
1595  LocalContext env;
1596  v8::HandleScope scope(env->GetIsolate());
1597  v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1598  CHECK(boxed_string->IsStringObject());
1599  v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1600  CHECK(!unboxed_string->IsStringObject());
1601  v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1602  CHECK(!boxed_not_string->IsStringObject());
1603  v8::Handle<Value> not_object = CompileRun("0");
1604  CHECK(!not_object->IsStringObject());
1605  v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1606  CHECK(!as_boxed.IsEmpty());
1607  Local<v8::String> the_string = as_boxed->ValueOf();
1608  CHECK(!the_string.IsEmpty());
1609  ExpectObject("\"test\"", the_string);
1610  v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1611  CHECK(new_boxed_string->IsStringObject());
1612  as_boxed = new_boxed_string.As<v8::StringObject>();
1613  the_string = as_boxed->ValueOf();
1614  CHECK(!the_string.IsEmpty());
1615  ExpectObject("\"test\"", the_string);
1616 }
1617 
1618 
1619 THREADED_TEST(NumberObject) {
1620  LocalContext env;
1621  v8::HandleScope scope(env->GetIsolate());
1622  v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1623  CHECK(boxed_number->IsNumberObject());
1624  v8::Handle<Value> unboxed_number = CompileRun("42");
1625  CHECK(!unboxed_number->IsNumberObject());
1626  v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1627  CHECK(!boxed_not_number->IsNumberObject());
1628  v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1629  CHECK(!as_boxed.IsEmpty());
1630  double the_number = as_boxed->ValueOf();
1631  CHECK_EQ(42.0, the_number);
1632  v8::Handle<v8::Value> new_boxed_number =
1633  v8::NumberObject::New(env->GetIsolate(), 43);
1634  CHECK(new_boxed_number->IsNumberObject());
1635  as_boxed = new_boxed_number.As<v8::NumberObject>();
1636  the_number = as_boxed->ValueOf();
1637  CHECK_EQ(43.0, the_number);
1638 }
1639 
1640 
1641 THREADED_TEST(BooleanObject) {
1642  LocalContext env;
1643  v8::HandleScope scope(env->GetIsolate());
1644  v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1645  CHECK(boxed_boolean->IsBooleanObject());
1646  v8::Handle<Value> unboxed_boolean = CompileRun("true");
1647  CHECK(!unboxed_boolean->IsBooleanObject());
1648  v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1649  CHECK(!boxed_not_boolean->IsBooleanObject());
1651  boxed_boolean.As<v8::BooleanObject>();
1652  CHECK(!as_boxed.IsEmpty());
1653  bool the_boolean = as_boxed->ValueOf();
1654  CHECK_EQ(true, the_boolean);
1655  v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1656  v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1657  CHECK(boxed_true->IsBooleanObject());
1658  CHECK(boxed_false->IsBooleanObject());
1659  as_boxed = boxed_true.As<v8::BooleanObject>();
1660  CHECK_EQ(true, as_boxed->ValueOf());
1661  as_boxed = boxed_false.As<v8::BooleanObject>();
1662  CHECK_EQ(false, as_boxed->ValueOf());
1663 }
1664 
1665 
1666 THREADED_TEST(PrimitiveAndWrappedBooleans) {
1667  LocalContext env;
1668  v8::HandleScope scope(env->GetIsolate());
1669 
1670  Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1671  CHECK(primitive_false->IsBoolean());
1672  CHECK(!primitive_false->IsBooleanObject());
1673  CHECK(!primitive_false->BooleanValue());
1674  CHECK(!primitive_false->IsTrue());
1675  CHECK(primitive_false->IsFalse());
1676 
1677  Local<Value> false_value = BooleanObject::New(false);
1678  CHECK(!false_value->IsBoolean());
1679  CHECK(false_value->IsBooleanObject());
1680  CHECK(false_value->BooleanValue());
1681  CHECK(!false_value->IsTrue());
1682  CHECK(!false_value->IsFalse());
1683 
1684  Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1685  CHECK(!false_boolean_object->IsBoolean());
1686  CHECK(false_boolean_object->IsBooleanObject());
1687  // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1688  // CHECK(false_boolean_object->BooleanValue());
1689  CHECK(!false_boolean_object->ValueOf());
1690  CHECK(!false_boolean_object->IsTrue());
1691  CHECK(!false_boolean_object->IsFalse());
1692 
1693  Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1694  CHECK(primitive_true->IsBoolean());
1695  CHECK(!primitive_true->IsBooleanObject());
1696  CHECK(primitive_true->BooleanValue());
1697  CHECK(primitive_true->IsTrue());
1698  CHECK(!primitive_true->IsFalse());
1699 
1700  Local<Value> true_value = BooleanObject::New(true);
1701  CHECK(!true_value->IsBoolean());
1702  CHECK(true_value->IsBooleanObject());
1703  CHECK(true_value->BooleanValue());
1704  CHECK(!true_value->IsTrue());
1705  CHECK(!true_value->IsFalse());
1706 
1707  Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1708  CHECK(!true_boolean_object->IsBoolean());
1709  CHECK(true_boolean_object->IsBooleanObject());
1710  // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1711  // CHECK(true_boolean_object->BooleanValue());
1712  CHECK(true_boolean_object->ValueOf());
1713  CHECK(!true_boolean_object->IsTrue());
1714  CHECK(!true_boolean_object->IsFalse());
1715 }
1716 
1717 
1718 THREADED_TEST(Number) {
1719  LocalContext env;
1720  v8::HandleScope scope(env->GetIsolate());
1721  double PI = 3.1415926;
1722  Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
1723  CHECK_EQ(PI, pi_obj->NumberValue());
1724 }
1725 
1726 
1728  LocalContext env;
1729  v8::Isolate* isolate = CcTest::isolate();
1730  v8::HandleScope scope(isolate);
1731  Local<String> str = v8_str("3.1415926");
1732  CHECK_EQ(3.1415926, str->NumberValue());
1733  v8::Handle<v8::Boolean> t = v8::True(isolate);
1734  CHECK_EQ(1.0, t->NumberValue());
1735  v8::Handle<v8::Boolean> f = v8::False(isolate);
1736  CHECK_EQ(0.0, f->NumberValue());
1737 }
1738 
1739 
1741  LocalContext env;
1742  v8::HandleScope scope(env->GetIsolate());
1743  double PI = 3.1415926;
1744  Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
1745  CHECK_EQ(3.0, date->NumberValue());
1746  date.As<v8::Date>()->Set(v8_str("property"),
1747  v8::Integer::New(env->GetIsolate(), 42));
1748  CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1749 }
1750 
1751 
1752 THREADED_TEST(Boolean) {
1753  LocalContext env;
1754  v8::Isolate* isolate = env->GetIsolate();
1755  v8::HandleScope scope(isolate);
1756  v8::Handle<v8::Boolean> t = v8::True(isolate);
1757  CHECK(t->Value());
1758  v8::Handle<v8::Boolean> f = v8::False(isolate);
1759  CHECK(!f->Value());
1761  CHECK(!u->BooleanValue());
1762  v8::Handle<v8::Primitive> n = v8::Null(isolate);
1763  CHECK(!n->BooleanValue());
1764  v8::Handle<String> str1 = v8_str("");
1765  CHECK(!str1->BooleanValue());
1766  v8::Handle<String> str2 = v8_str("x");
1767  CHECK(str2->BooleanValue());
1768  CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1769  CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1770  CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1771  CHECK(v8::Number::New(isolate, 42)->BooleanValue());
1772  CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1773 }
1774 
1775 
1776 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
1778  args.GetReturnValue().Set(v8_num(13.4));
1779 }
1780 
1781 
1782 static void GetM(Local<String> name,
1785  info.GetReturnValue().Set(v8_num(876));
1786 }
1787 
1788 
1789 THREADED_TEST(GlobalPrototype) {
1790  v8::Isolate* isolate = CcTest::isolate();
1791  v8::HandleScope scope(isolate);
1793  v8::FunctionTemplate::New(isolate);
1794  func_templ->PrototypeTemplate()->Set(
1795  isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
1796  v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1797  templ->Set(isolate, "x", v8_num(200));
1798  templ->SetAccessor(v8_str("m"), GetM);
1799  LocalContext env(0, templ);
1800  v8::Handle<Script> script(v8_compile("dummy()"));
1801  v8::Handle<Value> result(script->Run());
1802  CHECK_EQ(13.4, result->NumberValue());
1803  CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1804  CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1805 }
1806 
1807 
1808 THREADED_TEST(ObjectTemplate) {
1809  v8::Isolate* isolate = CcTest::isolate();
1810  v8::HandleScope scope(isolate);
1811  Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate);
1812  templ1->Set(isolate, "x", v8_num(10));
1813  templ1->Set(isolate, "y", v8_num(13));
1814  LocalContext env;
1815  Local<v8::Object> instance1 = templ1->NewInstance();
1816  env->Global()->Set(v8_str("p"), instance1);
1817  CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1818  CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1819  Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1820  fun->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1821  Local<ObjectTemplate> templ2 = fun->InstanceTemplate();
1822  templ2->Set(isolate, "a", v8_num(12));
1823  templ2->Set(isolate, "b", templ1);
1824  Local<v8::Object> instance2 = templ2->NewInstance();
1825  env->Global()->Set(v8_str("q"), instance2);
1826  CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1827  CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1828  CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1829  CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1830 }
1831 
1832 
1833 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
1835  args.GetReturnValue().Set(v8_num(17.2));
1836 }
1837 
1838 
1839 static void GetKnurd(Local<String> property,
1842  info.GetReturnValue().Set(v8_num(15.2));
1843 }
1844 
1845 
1846 THREADED_TEST(DescriptorInheritance) {
1847  v8::Isolate* isolate = CcTest::isolate();
1848  v8::HandleScope scope(isolate);
1850  super->PrototypeTemplate()->Set(isolate, "flabby",
1851  v8::FunctionTemplate::New(isolate,
1852  GetFlabby));
1853  super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
1854 
1855  super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1856 
1858  base1->Inherit(super);
1859  base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
1860 
1862  base2->Inherit(super);
1863  base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
1864 
1865  LocalContext env;
1866 
1867  env->Global()->Set(v8_str("s"), super->GetFunction());
1868  env->Global()->Set(v8_str("base1"), base1->GetFunction());
1869  env->Global()->Set(v8_str("base2"), base2->GetFunction());
1870 
1871  // Checks right __proto__ chain.
1872  CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1873  CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1874 
1875  CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1876 
1877  // Instance accessor should not be visible on function object or its prototype
1878  CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1879  CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1880  CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1881 
1882  env->Global()->Set(v8_str("obj"),
1883  base1->GetFunction()->NewInstance());
1884  CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1885  CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1886  CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1887  CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1888  CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1889 
1890  env->Global()->Set(v8_str("obj2"),
1891  base2->GetFunction()->NewInstance());
1892  CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1893  CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1894  CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1895  CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1896  CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1897 
1898  // base1 and base2 cannot cross reference to each's prototype
1899  CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1900  CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1901 }
1902 
1903 
1905 
1906 
1907 static void EchoNamedProperty(Local<String> name,
1910  CHECK_EQ(v8_str("data"), info.Data());
1911  echo_named_call_count++;
1912  info.GetReturnValue().Set(name);
1913 }
1914 
1915 
1916 // Helper functions for Interceptor/Accessor interaction tests
1917 
1918 void SimpleAccessorGetter(Local<String> name,
1920  Handle<Object> self = info.This();
1921  info.GetReturnValue().Set(
1922  self->Get(String::Concat(v8_str("accessor_"), name)));
1923 }
1924 
1925 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1926  const v8::PropertyCallbackInfo<void>& info) {
1927  Handle<Object> self = info.This();
1928  self->Set(String::Concat(v8_str("accessor_"), name), value);
1929 }
1930 
1931 void EmptyInterceptorGetter(Local<String> name,
1933 }
1934 
1935 void EmptyInterceptorSetter(Local<String> name,
1936  Local<Value> value,
1938 }
1939 
1940 void InterceptorGetter(Local<String> name,
1942  // Intercept names that start with 'interceptor_'.
1943  String::Utf8Value utf8(name);
1944  char* name_str = *utf8;
1945  char prefix[] = "interceptor_";
1946  int i;
1947  for (i = 0; name_str[i] && prefix[i]; ++i) {
1948  if (name_str[i] != prefix[i]) return;
1949  }
1950  Handle<Object> self = info.This();
1951  info.GetReturnValue().Set(self->GetHiddenValue(v8_str(name_str + i)));
1952 }
1953 
1954 void InterceptorSetter(Local<String> name,
1955  Local<Value> value,
1957  // Intercept accesses that set certain integer values, for which the name does
1958  // not start with 'accessor_'.
1959  String::Utf8Value utf8(name);
1960  char* name_str = *utf8;
1961  char prefix[] = "accessor_";
1962  int i;
1963  for (i = 0; name_str[i] && prefix[i]; ++i) {
1964  if (name_str[i] != prefix[i]) break;
1965  }
1966  if (!prefix[i]) return;
1967 
1968  if (value->IsInt32() && value->Int32Value() < 10000) {
1969  Handle<Object> self = info.This();
1970  self->SetHiddenValue(name, value);
1971  info.GetReturnValue().Set(value);
1972  }
1973 }
1974 
1975 void AddAccessor(Handle<FunctionTemplate> templ,
1976  Handle<String> name,
1978  v8::AccessorSetterCallback setter) {
1979  templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
1980 }
1981 
1982 void AddInterceptor(Handle<FunctionTemplate> templ,
1985  templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
1986 }
1987 
1988 
1989 THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
1991  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
1992  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
1993  child->Inherit(parent);
1994  AddAccessor(parent, v8_str("age"),
1997  LocalContext env;
1998  env->Global()->Set(v8_str("Child"), child->GetFunction());
1999  CompileRun("var child = new Child;"
2000  "child.age = 10;");
2001  ExpectBoolean("child.hasOwnProperty('age')", false);
2002  ExpectInt32("child.age", 10);
2003  ExpectInt32("child.accessor_age", 10);
2004 }
2005 
2006 
2007 THREADED_TEST(EmptyInterceptorBreakTransitions) {
2009  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2011  LocalContext env;
2012  env->Global()->Set(v8_str("Constructor"), templ->GetFunction());
2013  CompileRun("var o1 = new Constructor;"
2014  "o1.a = 1;" // Ensure a and x share the descriptor array.
2015  "Object.defineProperty(o1, 'x', {value: 10});");
2016  CompileRun("var o2 = new Constructor;"
2017  "o2.a = 1;"
2018  "Object.defineProperty(o2, 'x', {value: 10});");
2019 }
2020 
2021 
2022 THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
2023  v8::Isolate* isolate = CcTest::isolate();
2024  v8::HandleScope scope(isolate);
2025  Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2026  Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
2027  child->Inherit(parent);
2029  LocalContext env;
2030  env->Global()->Set(v8_str("Child"), child->GetFunction());
2031  CompileRun("var child = new Child;"
2032  "var parent = child.__proto__;"
2033  "Object.defineProperty(parent, 'age', "
2034  " {get: function(){ return this.accessor_age; }, "
2035  " set: function(v){ this.accessor_age = v; }, "
2036  " enumerable: true, configurable: true});"
2037  "child.age = 10;");
2038  ExpectBoolean("child.hasOwnProperty('age')", false);
2039  ExpectInt32("child.age", 10);
2040  ExpectInt32("child.accessor_age", 10);
2041 }
2042 
2043 
2044 THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
2045  v8::Isolate* isolate = CcTest::isolate();
2046  v8::HandleScope scope(isolate);
2047  Handle<FunctionTemplate> parent = FunctionTemplate::New(isolate);
2048  Handle<FunctionTemplate> child = FunctionTemplate::New(isolate);
2049  child->Inherit(parent);
2051  LocalContext env;
2052  env->Global()->Set(v8_str("Child"), child->GetFunction());
2053  CompileRun("var child = new Child;"
2054  "var parent = child.__proto__;"
2055  "parent.name = 'Alice';");
2056  ExpectBoolean("child.hasOwnProperty('name')", false);
2057  ExpectString("child.name", "Alice");
2058  CompileRun("child.name = 'Bob';");
2059  ExpectString("child.name", "Bob");
2060  ExpectBoolean("child.hasOwnProperty('name')", true);
2061  ExpectString("parent.name", "Alice");
2062 }
2063 
2064 
2065 THREADED_TEST(SwitchFromInterceptorToAccessor) {
2067  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2068  AddAccessor(templ, v8_str("age"),
2071  LocalContext env;
2072  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2073  CompileRun("var obj = new Obj;"
2074  "function setAge(i){ obj.age = i; };"
2075  "for(var i = 0; i <= 10000; i++) setAge(i);");
2076  // All i < 10000 go to the interceptor.
2077  ExpectInt32("obj.interceptor_age", 9999);
2078  // The last i goes to the accessor.
2079  ExpectInt32("obj.accessor_age", 10000);
2080 }
2081 
2082 
2083 THREADED_TEST(SwitchFromAccessorToInterceptor) {
2085  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2086  AddAccessor(templ, v8_str("age"),
2089  LocalContext env;
2090  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2091  CompileRun("var obj = new Obj;"
2092  "function setAge(i){ obj.age = i; };"
2093  "for(var i = 20000; i >= 9999; i--) setAge(i);");
2094  // All i >= 10000 go to the accessor.
2095  ExpectInt32("obj.accessor_age", 10000);
2096  // The last i goes to the interceptor.
2097  ExpectInt32("obj.interceptor_age", 9999);
2098 }
2099 
2100 
2101 THREADED_TEST(SwitchFromInterceptorToAccessorWithInheritance) {
2103  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2104  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
2105  child->Inherit(parent);
2106  AddAccessor(parent, v8_str("age"),
2109  LocalContext env;
2110  env->Global()->Set(v8_str("Child"), child->GetFunction());
2111  CompileRun("var child = new Child;"
2112  "function setAge(i){ child.age = i; };"
2113  "for(var i = 0; i <= 10000; i++) setAge(i);");
2114  // All i < 10000 go to the interceptor.
2115  ExpectInt32("child.interceptor_age", 9999);
2116  // The last i goes to the accessor.
2117  ExpectInt32("child.accessor_age", 10000);
2118 }
2119 
2120 
2121 THREADED_TEST(SwitchFromAccessorToInterceptorWithInheritance) {
2123  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2124  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
2125  child->Inherit(parent);
2126  AddAccessor(parent, v8_str("age"),
2129  LocalContext env;
2130  env->Global()->Set(v8_str("Child"), child->GetFunction());
2131  CompileRun("var child = new Child;"
2132  "function setAge(i){ child.age = i; };"
2133  "for(var i = 20000; i >= 9999; i--) setAge(i);");
2134  // All i >= 10000 go to the accessor.
2135  ExpectInt32("child.accessor_age", 10000);
2136  // The last i goes to the interceptor.
2137  ExpectInt32("child.interceptor_age", 9999);
2138 }
2139 
2140 
2141 THREADED_TEST(SwitchFromInterceptorToJSAccessor) {
2143  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2145  LocalContext env;
2146  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2147  CompileRun("var obj = new Obj;"
2148  "function setter(i) { this.accessor_age = i; };"
2149  "function getter() { return this.accessor_age; };"
2150  "function setAge(i) { obj.age = i; };"
2151  "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2152  "for(var i = 0; i <= 10000; i++) setAge(i);");
2153  // All i < 10000 go to the interceptor.
2154  ExpectInt32("obj.interceptor_age", 9999);
2155  // The last i goes to the JavaScript accessor.
2156  ExpectInt32("obj.accessor_age", 10000);
2157  // The installed JavaScript getter is still intact.
2158  // This last part is a regression test for issue 1651 and relies on the fact
2159  // that both interceptor and accessor are being installed on the same object.
2160  ExpectInt32("obj.age", 10000);
2161  ExpectBoolean("obj.hasOwnProperty('age')", true);
2162  ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2163 }
2164 
2165 
2166 THREADED_TEST(SwitchFromJSAccessorToInterceptor) {
2168  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
2170  LocalContext env;
2171  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
2172  CompileRun("var obj = new Obj;"
2173  "function setter(i) { this.accessor_age = i; };"
2174  "function getter() { return this.accessor_age; };"
2175  "function setAge(i) { obj.age = i; };"
2176  "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
2177  "for(var i = 20000; i >= 9999; i--) setAge(i);");
2178  // All i >= 10000 go to the accessor.
2179  ExpectInt32("obj.accessor_age", 10000);
2180  // The last i goes to the interceptor.
2181  ExpectInt32("obj.interceptor_age", 9999);
2182  // The installed JavaScript getter is still intact.
2183  // This last part is a regression test for issue 1651 and relies on the fact
2184  // that both interceptor and accessor are being installed on the same object.
2185  ExpectInt32("obj.age", 10000);
2186  ExpectBoolean("obj.hasOwnProperty('age')", true);
2187  ExpectUndefined("Object.getOwnPropertyDescriptor(obj, 'age').value");
2188 }
2189 
2190 
2191 THREADED_TEST(SwitchFromInterceptorToProperty) {
2193  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2194  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
2195  child->Inherit(parent);
2197  LocalContext env;
2198  env->Global()->Set(v8_str("Child"), child->GetFunction());
2199  CompileRun("var child = new Child;"
2200  "function setAge(i){ child.age = i; };"
2201  "for(var i = 0; i <= 10000; i++) setAge(i);");
2202  // All i < 10000 go to the interceptor.
2203  ExpectInt32("child.interceptor_age", 9999);
2204  // The last i goes to child's own property.
2205  ExpectInt32("child.age", 10000);
2206 }
2207 
2208 
2209 THREADED_TEST(SwitchFromPropertyToInterceptor) {
2211  Handle<FunctionTemplate> parent = FunctionTemplate::New(CcTest::isolate());
2212  Handle<FunctionTemplate> child = FunctionTemplate::New(CcTest::isolate());
2213  child->Inherit(parent);
2215  LocalContext env;
2216  env->Global()->Set(v8_str("Child"), child->GetFunction());
2217  CompileRun("var child = new Child;"
2218  "function setAge(i){ child.age = i; };"
2219  "for(var i = 20000; i >= 9999; i--) setAge(i);");
2220  // All i >= 10000 go to child's own property.
2221  ExpectInt32("child.age", 10000);
2222  // The last i goes to the interceptor.
2223  ExpectInt32("child.interceptor_age", 9999);
2224 }
2225 
2226 
2227 THREADED_TEST(NamedPropertyHandlerGetter) {
2228  echo_named_call_count = 0;
2232  templ->InstanceTemplate()->SetNamedPropertyHandler(EchoNamedProperty,
2233  0, 0, 0, 0,
2234  v8_str("data"));
2235  LocalContext env;
2236  env->Global()->Set(v8_str("obj"),
2237  templ->GetFunction()->NewInstance());
2238  CHECK_EQ(echo_named_call_count, 0);
2239  v8_compile("obj.x")->Run();
2240  CHECK_EQ(echo_named_call_count, 1);
2241  const char* code = "var str = 'oddle'; obj[str] + obj.poddle;";
2242  v8::Handle<Value> str = CompileRun(code);
2243  String::Utf8Value value(str);
2244  CHECK_EQ(*value, "oddlepoddle");
2245  // Check default behavior
2246  CHECK_EQ(v8_compile("obj.flob = 10;")->Run()->Int32Value(), 10);
2247  CHECK(v8_compile("'myProperty' in obj")->Run()->BooleanValue());
2248  CHECK(v8_compile("delete obj.myProperty")->Run()->BooleanValue());
2249 }
2250 
2251 
2253 
2254 
2255 static void EchoIndexedProperty(
2256  uint32_t index,
2259  CHECK_EQ(v8_num(637), info.Data());
2260  echo_indexed_call_count++;
2261  info.GetReturnValue().Set(v8_num(index));
2262 }
2263 
2264 
2265 THREADED_TEST(IndexedPropertyHandlerGetter) {
2266  v8::Isolate* isolate = CcTest::isolate();
2267  v8::HandleScope scope(isolate);
2269  templ->InstanceTemplate()->SetIndexedPropertyHandler(EchoIndexedProperty,
2270  0, 0, 0, 0,
2271  v8_num(637));
2272  LocalContext env;
2273  env->Global()->Set(v8_str("obj"),
2274  templ->GetFunction()->NewInstance());
2275  Local<Script> script = v8_compile("obj[900]");
2276  CHECK_EQ(script->Run()->Int32Value(), 900);
2277 }
2278 
2279 
2281 
2282 static void CheckThisIndexedPropertyHandler(
2283  uint32_t index,
2285  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyHandler));
2287  CHECK(info.This()->Equals(bottom));
2288 }
2289 
2290 static void CheckThisNamedPropertyHandler(
2291  Local<String> name,
2293  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyHandler));
2295  CHECK(info.This()->Equals(bottom));
2296 }
2297 
2299  uint32_t index,
2300  Local<Value> value,
2302  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertySetter));
2304  CHECK(info.This()->Equals(bottom));
2305 }
2306 
2307 
2309  Local<String> property,
2310  Local<Value> value,
2312  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertySetter));
2314  CHECK(info.This()->Equals(bottom));
2315 }
2316 
2318  uint32_t index,
2320  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyQuery));
2322  CHECK(info.This()->Equals(bottom));
2323 }
2324 
2325 
2327  Local<String> property,
2329  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyQuery));
2331  CHECK(info.This()->Equals(bottom));
2332 }
2333 
2334 
2336  uint32_t index,
2338  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyDeleter));
2340  CHECK(info.This()->Equals(bottom));
2341 }
2342 
2343 
2345  Local<String> property,
2347  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyDeleter));
2349  CHECK(info.This()->Equals(bottom));
2350 }
2351 
2352 
2355  CheckReturnValue(info, FUNCTION_ADDR(CheckThisIndexedPropertyEnumerator));
2357  CHECK(info.This()->Equals(bottom));
2358 }
2359 
2360 
2363  CheckReturnValue(info, FUNCTION_ADDR(CheckThisNamedPropertyEnumerator));
2365  CHECK(info.This()->Equals(bottom));
2366 }
2367 
2368 
2369 THREADED_PROFILED_TEST(PropertyHandlerInPrototype) {
2370  LocalContext env;
2371  v8::Isolate* isolate = env->GetIsolate();
2372  v8::HandleScope scope(isolate);
2373 
2374  // Set up a prototype chain with three interceptors.
2376  templ->InstanceTemplate()->SetIndexedPropertyHandler(
2377  CheckThisIndexedPropertyHandler,
2382 
2383  templ->InstanceTemplate()->SetNamedPropertyHandler(
2384  CheckThisNamedPropertyHandler,
2389 
2390  bottom = templ->GetFunction()->NewInstance();
2391  Local<v8::Object> top = templ->GetFunction()->NewInstance();
2392  Local<v8::Object> middle = templ->GetFunction()->NewInstance();
2393 
2394  bottom->SetPrototype(middle);
2395  middle->SetPrototype(top);
2396  env->Global()->Set(v8_str("obj"), bottom);
2397 
2398  // Indexed and named get.
2399  CompileRun("obj[0]");
2400  CompileRun("obj.x");
2401 
2402  // Indexed and named set.
2403  CompileRun("obj[1] = 42");
2404  CompileRun("obj.y = 42");
2405 
2406  // Indexed and named query.
2407  CompileRun("0 in obj");
2408  CompileRun("'x' in obj");
2409 
2410  // Indexed and named deleter.
2411  CompileRun("delete obj[0]");
2412  CompileRun("delete obj.x");
2413 
2414  // Enumerators.
2415  CompileRun("for (var p in obj) ;");
2416 }
2417 
2418 
2419 static void PrePropertyHandlerGet(
2420  Local<String> key,
2423  if (v8_str("pre")->Equals(key)) {
2424  info.GetReturnValue().Set(v8_str("PrePropertyHandler: pre"));
2425  }
2426 }
2427 
2428 
2429 static void PrePropertyHandlerQuery(
2430  Local<String> key,
2432  if (v8_str("pre")->Equals(key)) {
2433  info.GetReturnValue().Set(static_cast<int32_t>(v8::None));
2434  }
2435 }
2436 
2437 
2438 THREADED_TEST(PrePropertyHandler) {
2439  v8::Isolate* isolate = CcTest::isolate();
2440  v8::HandleScope scope(isolate);
2442  desc->InstanceTemplate()->SetNamedPropertyHandler(PrePropertyHandlerGet,
2443  0,
2444  PrePropertyHandlerQuery);
2445  LocalContext env(NULL, desc->InstanceTemplate());
2446  CompileRun("var pre = 'Object: pre'; var on = 'Object: on';");
2447  v8::Handle<Value> result_pre = CompileRun("pre");
2448  CHECK_EQ(v8_str("PrePropertyHandler: pre"), result_pre);
2449  v8::Handle<Value> result_on = CompileRun("on");
2450  CHECK_EQ(v8_str("Object: on"), result_on);
2451  v8::Handle<Value> result_post = CompileRun("post");
2452  CHECK(result_post.IsEmpty());
2453 }
2454 
2455 
2456 THREADED_TEST(UndefinedIsNotEnumerable) {
2457  LocalContext env;
2458  v8::HandleScope scope(env->GetIsolate());
2459  v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
2460  CHECK(result->IsFalse());
2461 }
2462 
2463 
2465 static const int kTargetRecursionDepth = 200; // near maximum
2466 
2467 
2468 static void CallScriptRecursivelyCall(
2471  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2472  if (depth == kTargetRecursionDepth) return;
2473  args.This()->Set(v8_str("depth"),
2474  v8::Integer::New(args.GetIsolate(), depth + 1));
2475  args.GetReturnValue().Set(call_recursively_script->Run());
2476 }
2477 
2478 
2479 static void CallFunctionRecursivelyCall(
2482  int depth = args.This()->Get(v8_str("depth"))->Int32Value();
2483  if (depth == kTargetRecursionDepth) {
2484  printf("[depth = %d]\n", depth);
2485  return;
2486  }
2487  args.This()->Set(v8_str("depth"),
2488  v8::Integer::New(args.GetIsolate(), depth + 1));
2489  v8::Handle<Value> function =
2490  args.This()->Get(v8_str("callFunctionRecursively"));
2491  args.GetReturnValue().Set(
2492  function.As<Function>()->Call(args.This(), 0, NULL));
2493 }
2494 
2495 
2496 THREADED_TEST(DeepCrossLanguageRecursion) {
2497  v8::Isolate* isolate = CcTest::isolate();
2498  v8::HandleScope scope(isolate);
2499  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
2500  global->Set(v8_str("callScriptRecursively"),
2501  v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
2502  global->Set(v8_str("callFunctionRecursively"),
2503  v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
2504  LocalContext env(NULL, global);
2505 
2506  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
2507  call_recursively_script = v8_compile("callScriptRecursively()");
2508  call_recursively_script->Run();
2509  call_recursively_script = v8::Handle<Script>();
2510 
2511  env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
2512  CompileRun("callFunctionRecursively()");
2513 }
2514 
2515 
2516 static void ThrowingPropertyHandlerGet(
2517  Local<String> key,
2520  info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
2521 }
2522 
2523 
2524 static void ThrowingPropertyHandlerSet(
2525  Local<String> key,
2526  Local<Value>,
2528  info.GetIsolate()->ThrowException(key);
2529  info.GetReturnValue().SetUndefined(); // not the same as empty handle
2530 }
2531 
2532 
2533 THREADED_TEST(CallbackExceptionRegression) {
2534  v8::Isolate* isolate = CcTest::isolate();
2535  v8::HandleScope scope(isolate);
2536  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
2537  obj->SetNamedPropertyHandler(ThrowingPropertyHandlerGet,
2538  ThrowingPropertyHandlerSet);
2539  LocalContext env;
2540  env->Global()->Set(v8_str("obj"), obj->NewInstance());
2541  v8::Handle<Value> otto = CompileRun(
2542  "try { with (obj) { otto; } } catch (e) { e; }");
2543  CHECK_EQ(v8_str("otto"), otto);
2544  v8::Handle<Value> netto = CompileRun(
2545  "try { with (obj) { netto = 4; } } catch (e) { e; }");
2546  CHECK_EQ(v8_str("netto"), netto);
2547 }
2548 
2549 
2550 THREADED_TEST(FunctionPrototype) {
2551  v8::Isolate* isolate = CcTest::isolate();
2552  v8::HandleScope scope(isolate);
2553  Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
2554  Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2555  LocalContext env;
2556  env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2557  Local<Script> script = v8_compile("Foo.prototype.plak");
2558  CHECK_EQ(script->Run()->Int32Value(), 321);
2559 }
2560 
2561 
2562 THREADED_TEST(InternalFields) {
2563  LocalContext env;
2564  v8::Isolate* isolate = env->GetIsolate();
2565  v8::HandleScope scope(isolate);
2566 
2567  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2568  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2569  instance_templ->SetInternalFieldCount(1);
2570  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2571  CHECK_EQ(1, obj->InternalFieldCount());
2572  CHECK(obj->GetInternalField(0)->IsUndefined());
2573  obj->SetInternalField(0, v8_num(17));
2574  CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2575 }
2576 
2577 
2578 THREADED_TEST(GlobalObjectInternalFields) {
2579  v8::Isolate* isolate = CcTest::isolate();
2580  v8::HandleScope scope(isolate);
2581  Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
2582  global_template->SetInternalFieldCount(1);
2583  LocalContext env(NULL, global_template);
2584  v8::Handle<v8::Object> global_proxy = env->Global();
2585  v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2586  CHECK_EQ(1, global->InternalFieldCount());
2587  CHECK(global->GetInternalField(0)->IsUndefined());
2588  global->SetInternalField(0, v8_num(17));
2589  CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2590 }
2591 
2592 
2593 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2594  LocalContext env;
2596 
2597  v8::Local<v8::Object> global = env->Global();
2598  global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
2599  CHECK(global->HasRealIndexedProperty(0));
2600 }
2601 
2602 
2603 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2604  void* value) {
2605  CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2606  obj->SetAlignedPointerInInternalField(0, value);
2608  CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2609 }
2610 
2611 
2612 THREADED_TEST(InternalFieldsAlignedPointers) {
2613  LocalContext env;
2614  v8::Isolate* isolate = env->GetIsolate();
2615  v8::HandleScope scope(isolate);
2616 
2617  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2618  Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2619  instance_templ->SetInternalFieldCount(1);
2620  Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2621  CHECK_EQ(1, obj->InternalFieldCount());
2622 
2623  CheckAlignedPointerInInternalField(obj, NULL);
2624 
2625  int* heap_allocated = new int[100];
2626  CheckAlignedPointerInInternalField(obj, heap_allocated);
2627  delete[] heap_allocated;
2628 
2629  int stack_allocated[100];
2630  CheckAlignedPointerInInternalField(obj, stack_allocated);
2631 
2632  void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2633  CheckAlignedPointerInInternalField(obj, huge);
2634 
2635  v8::UniquePersistent<v8::Object> persistent(isolate, obj);
2636  CHECK_EQ(1, Object::InternalFieldCount(persistent));
2637  CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2638 }
2639 
2640 
2641 static void CheckAlignedPointerInEmbedderData(LocalContext* env,
2642  int index,
2643  void* value) {
2644  CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2645  (*env)->SetAlignedPointerInEmbedderData(index, value);
2647  CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2648 }
2649 
2650 
2651 static void* AlignedTestPointer(int i) {
2652  return reinterpret_cast<void*>(i * 1234);
2653 }
2654 
2655 
2656 THREADED_TEST(EmbedderDataAlignedPointers) {
2657  LocalContext env;
2658  v8::HandleScope scope(env->GetIsolate());
2659 
2660  CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2661 
2662  int* heap_allocated = new int[100];
2663  CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2664  delete[] heap_allocated;
2665 
2666  int stack_allocated[100];
2667  CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2668 
2669  void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2670  CheckAlignedPointerInEmbedderData(&env, 3, huge);
2671 
2672  // Test growing of the embedder data's backing store.
2673  for (int i = 0; i < 100; i++) {
2674  env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2675  }
2677  for (int i = 0; i < 100; i++) {
2678  CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2679  }
2680 }
2681 
2682 
2683 static void CheckEmbedderData(LocalContext* env,
2684  int index,
2685  v8::Handle<Value> data) {
2686  (*env)->SetEmbedderData(index, data);
2687  CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2688 }
2689 
2690 
2691 THREADED_TEST(EmbedderData) {
2692  LocalContext env;
2693  v8::Isolate* isolate = env->GetIsolate();
2694  v8::HandleScope scope(isolate);
2695 
2696  CheckEmbedderData(
2697  &env, 3,
2698  v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2699  CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(isolate,
2700  "over the lazy dog."));
2701  CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2702  CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
2703 }
2704 
2705 
2706 THREADED_TEST(IdentityHash) {
2707  LocalContext env;
2708  v8::Isolate* isolate = env->GetIsolate();
2709  v8::HandleScope scope(isolate);
2710 
2711  // Ensure that the test starts with an fresh heap to test whether the hash
2712  // code is based on the address.
2714  Local<v8::Object> obj = v8::Object::New(isolate);
2715  int hash = obj->GetIdentityHash();
2716  int hash1 = obj->GetIdentityHash();
2717  CHECK_EQ(hash, hash1);
2718  int hash2 = v8::Object::New(isolate)->GetIdentityHash();
2719  // Since the identity hash is essentially a random number two consecutive
2720  // objects should not be assigned the same hash code. If the test below fails
2721  // the random number generator should be evaluated.
2722  CHECK_NE(hash, hash2);
2724  int hash3 = v8::Object::New(isolate)->GetIdentityHash();
2725  // Make sure that the identity hash is not based on the initial address of
2726  // the object alone. If the test below fails the random number generator
2727  // should be evaluated.
2728  CHECK_NE(hash, hash3);
2729  int hash4 = obj->GetIdentityHash();
2730  CHECK_EQ(hash, hash4);
2731 
2732  // Check identity hashes behaviour in the presence of JS accessors.
2733  // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2734  {
2735  CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2736  Local<v8::Object> o1 = v8::Object::New(isolate);
2737  Local<v8::Object> o2 = v8::Object::New(isolate);
2738  CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2739  }
2740  {
2741  CompileRun(
2742  "function cnst() { return 42; };\n"
2743  "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2744  Local<v8::Object> o1 = v8::Object::New(isolate);
2745  Local<v8::Object> o2 = v8::Object::New(isolate);
2746  CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2747  }
2748 }
2749 
2750 
2751 THREADED_TEST(SymbolProperties) {
2752  i::FLAG_harmony_symbols = true;
2753 
2754  LocalContext env;
2755  v8::Isolate* isolate = env->GetIsolate();
2756  v8::HandleScope scope(isolate);
2757 
2758  v8::Local<v8::Object> obj = v8::Object::New(isolate);
2759  v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2760  v8::Local<v8::Symbol> sym2 =
2761  v8::Symbol::New(isolate, v8_str("my-symbol"));
2762 
2764 
2765  // Check basic symbol functionality.
2766  CHECK(sym1->IsSymbol());
2767  CHECK(sym2->IsSymbol());
2768  CHECK(!obj->IsSymbol());
2769 
2770  CHECK(sym1->Equals(sym1));
2771  CHECK(sym2->Equals(sym2));
2772  CHECK(!sym1->Equals(sym2));
2773  CHECK(!sym2->Equals(sym1));
2774  CHECK(sym1->StrictEquals(sym1));
2775  CHECK(sym2->StrictEquals(sym2));
2776  CHECK(!sym1->StrictEquals(sym2));
2777  CHECK(!sym2->StrictEquals(sym1));
2778 
2779  CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
2780 
2781  v8::Local<v8::Value> sym_val = sym2;
2782  CHECK(sym_val->IsSymbol());
2783  CHECK(sym_val->Equals(sym2));
2784  CHECK(sym_val->StrictEquals(sym2));
2785  CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2786 
2787  v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2788  CHECK(sym_obj->IsSymbolObject());
2789  CHECK(!sym2->IsSymbolObject());
2790  CHECK(!obj->IsSymbolObject());
2791  CHECK(!sym_obj->Equals(sym2));
2792  CHECK(!sym_obj->StrictEquals(sym2));
2793  CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2794  CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
2795 
2796  // Make sure delete of a non-existent symbol property works.
2797  CHECK(obj->Delete(sym1));
2798  CHECK(!obj->Has(sym1));
2799 
2800  CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
2801  CHECK(obj->Has(sym1));
2802  CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2803  CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
2804  CHECK(obj->Has(sym1));
2805  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2807 
2808  CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2809  int num_props = obj->GetPropertyNames()->Length();
2810  CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2811  v8::Integer::New(isolate, 20)));
2812  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2813  CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2814 
2816 
2817  // Add another property and delete it afterwards to force the object in
2818  // slow case.
2819  CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
2820  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2821  CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2822  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2823  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2824 
2825  CHECK(obj->Has(sym1));
2826  CHECK(obj->Has(sym2));
2827  CHECK(obj->Delete(sym2));
2828  CHECK(obj->Has(sym1));
2829  CHECK(!obj->Has(sym2));
2830  CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2831  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2832 
2833  // Symbol properties are inherited.
2834  v8::Local<v8::Object> child = v8::Object::New(isolate);
2835  child->SetPrototype(obj);
2836  CHECK(child->Has(sym1));
2837  CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2838  CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2839 }
2840 
2841 
2842 THREADED_TEST(PrivateProperties) {
2843  LocalContext env;
2844  v8::Isolate* isolate = env->GetIsolate();
2845  v8::HandleScope scope(isolate);
2846 
2847  v8::Local<v8::Object> obj = v8::Object::New(isolate);
2848  v8::Local<v8::Private> priv1 = v8::Private::New(isolate);
2849  v8::Local<v8::Private> priv2 =
2850  v8::Private::New(isolate, v8_str("my-private"));
2851 
2853 
2854  CHECK(priv2->Name()->Equals(v8::String::NewFromUtf8(isolate, "my-private")));
2855 
2856  // Make sure delete of a non-existent private symbol property works.
2857  CHECK(obj->DeletePrivate(priv1));
2858  CHECK(!obj->HasPrivate(priv1));
2859 
2860  CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 1503)));
2861  CHECK(obj->HasPrivate(priv1));
2862  CHECK_EQ(1503, obj->GetPrivate(priv1)->Int32Value());
2863  CHECK(obj->SetPrivate(priv1, v8::Integer::New(isolate, 2002)));
2864  CHECK(obj->HasPrivate(priv1));
2865  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2866 
2867  CHECK_EQ(0, obj->GetOwnPropertyNames()->Length());
2868  int num_props = obj->GetPropertyNames()->Length();
2869  CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2870  v8::Integer::New(isolate, 20)));
2871  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2872  CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2873 
2875 
2876  // Add another property and delete it afterwards to force the object in
2877  // slow case.
2878  CHECK(obj->SetPrivate(priv2, v8::Integer::New(isolate, 2008)));
2879  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2880  CHECK_EQ(2008, obj->GetPrivate(priv2)->Int32Value());
2881  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2882  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2883 
2884  CHECK(obj->HasPrivate(priv1));
2885  CHECK(obj->HasPrivate(priv2));
2886  CHECK(obj->DeletePrivate(priv2));
2887  CHECK(obj->HasPrivate(priv1));
2888  CHECK(!obj->HasPrivate(priv2));
2889  CHECK_EQ(2002, obj->GetPrivate(priv1)->Int32Value());
2890  CHECK_EQ(1, obj->GetOwnPropertyNames()->Length());
2891 
2892  // Private properties are inherited (for the time being).
2893  v8::Local<v8::Object> child = v8::Object::New(isolate);
2894  child->SetPrototype(obj);
2895  CHECK(child->HasPrivate(priv1));
2896  CHECK_EQ(2002, child->GetPrivate(priv1)->Int32Value());
2897  CHECK_EQ(0, child->GetOwnPropertyNames()->Length());
2898 }
2899 
2900 
2901 THREADED_TEST(GlobalSymbols) {
2902  i::FLAG_harmony_symbols = true;
2903 
2904  LocalContext env;
2905  v8::Isolate* isolate = env->GetIsolate();
2906  v8::HandleScope scope(isolate);
2907 
2908  v8::Local<String> name = v8_str("my-symbol");
2909  v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
2910  v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
2911  CHECK(glob2->SameValue(glob));
2912 
2913  v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
2914  v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
2915  CHECK(glob_api2->SameValue(glob_api));
2916  CHECK(!glob_api->SameValue(glob));
2917 
2918  v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
2919  CHECK(!sym->SameValue(glob));
2920 
2921  CompileRun("var sym2 = Symbol.for('my-symbol')");
2922  v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
2923  CHECK(sym2->SameValue(glob));
2924  CHECK(!sym2->SameValue(glob_api));
2925 }
2926 
2927 
2928 THREADED_TEST(GlobalPrivates) {
2929  LocalContext env;
2930  v8::Isolate* isolate = env->GetIsolate();
2931  v8::HandleScope scope(isolate);
2932 
2933  v8::Local<String> name = v8_str("my-private");
2934  v8::Local<v8::Private> glob = v8::Private::ForApi(isolate, name);
2935  v8::Local<v8::Object> obj = v8::Object::New(isolate);
2936  CHECK(obj->SetPrivate(glob, v8::Integer::New(isolate, 3)));
2937 
2938  v8::Local<v8::Private> glob2 = v8::Private::ForApi(isolate, name);
2939  CHECK(obj->HasPrivate(glob2));
2940 
2941  v8::Local<v8::Private> priv = v8::Private::New(isolate, name);
2942  CHECK(!obj->HasPrivate(priv));
2943 
2944  CompileRun("var intern = %CreateGlobalPrivateSymbol('my-private')");
2945  v8::Local<Value> intern = env->Global()->Get(v8_str("intern"));
2946  CHECK(!obj->Has(intern));
2947 }
2948 
2949 
2951  public:
2953  const v8::ArrayBuffer::Contents& contents)
2954  : contents_(contents) {}
2955  ~ScopedArrayBufferContents() { free(contents_.Data()); }
2956  void* Data() const { return contents_.Data(); }
2957  size_t ByteLength() const { return contents_.ByteLength(); }
2958  private:
2959  const v8::ArrayBuffer::Contents contents_;
2960 };
2961 
2962 template <typename T>
2963 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2964  CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2965  for (int i = 0; i < value->InternalFieldCount(); i++) {
2966  CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2967  }
2968 }
2969 
2970 
2971 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
2972  LocalContext env;
2973  v8::Isolate* isolate = env->GetIsolate();
2974  v8::HandleScope handle_scope(isolate);
2975 
2976  Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
2977  CheckInternalFieldsAreZero(ab);
2978  CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2979  CHECK(!ab->IsExternal());
2981 
2982  ScopedArrayBufferContents ab_contents(ab->Externalize());
2983  CHECK(ab->IsExternal());
2984 
2985  CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2986  uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2987  ASSERT(data != NULL);
2988  env->Global()->Set(v8_str("ab"), ab);
2989 
2990  v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2991  CHECK_EQ(1024, result->Int32Value());
2992 
2993  result = CompileRun("var u8 = new Uint8Array(ab);"
2994  "u8[0] = 0xFF;"
2995  "u8[1] = 0xAA;"
2996  "u8.length");
2997  CHECK_EQ(1024, result->Int32Value());
2998  CHECK_EQ(0xFF, data[0]);
2999  CHECK_EQ(0xAA, data[1]);
3000  data[0] = 0xCC;
3001  data[1] = 0x11;
3002  result = CompileRun("u8[0] + u8[1]");
3003  CHECK_EQ(0xDD, result->Int32Value());
3004 }
3005 
3006 
3007 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
3008  LocalContext env;
3009  v8::Isolate* isolate = env->GetIsolate();
3010  v8::HandleScope handle_scope(isolate);
3011 
3012 
3013  v8::Local<v8::Value> result =
3014  CompileRun("var ab1 = new ArrayBuffer(2);"
3015  "var u8_a = new Uint8Array(ab1);"
3016  "u8_a[0] = 0xAA;"
3017  "u8_a[1] = 0xFF; u8_a.buffer");
3018  Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
3019  CheckInternalFieldsAreZero(ab1);
3020  CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
3021  CHECK(!ab1->IsExternal());
3022  ScopedArrayBufferContents ab1_contents(ab1->Externalize());
3023  CHECK(ab1->IsExternal());
3024 
3025  result = CompileRun("ab1.byteLength");
3026  CHECK_EQ(2, result->Int32Value());
3027  result = CompileRun("u8_a[0]");
3028  CHECK_EQ(0xAA, result->Int32Value());
3029  result = CompileRun("u8_a[1]");
3030  CHECK_EQ(0xFF, result->Int32Value());
3031  result = CompileRun("var u8_b = new Uint8Array(ab1);"
3032  "u8_b[0] = 0xBB;"
3033  "u8_a[0]");
3034  CHECK_EQ(0xBB, result->Int32Value());
3035  result = CompileRun("u8_b[1]");
3036  CHECK_EQ(0xFF, result->Int32Value());
3037 
3038  CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
3039  uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
3040  CHECK_EQ(0xBB, ab1_data[0]);
3041  CHECK_EQ(0xFF, ab1_data[1]);
3042  ab1_data[0] = 0xCC;
3043  ab1_data[1] = 0x11;
3044  result = CompileRun("u8_a[0] + u8_a[1]");
3045  CHECK_EQ(0xDD, result->Int32Value());
3046 }
3047 
3048 
3049 THREADED_TEST(ArrayBuffer_External) {
3050  LocalContext env;
3051  v8::Isolate* isolate = env->GetIsolate();
3052  v8::HandleScope handle_scope(isolate);
3053 
3054  i::ScopedVector<uint8_t> my_data(100);
3055  memset(my_data.start(), 0, 100);
3056  Local<v8::ArrayBuffer> ab3 =
3057  v8::ArrayBuffer::New(isolate, my_data.start(), 100);
3058  CheckInternalFieldsAreZero(ab3);
3059  CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
3060  CHECK(ab3->IsExternal());
3061 
3062  env->Global()->Set(v8_str("ab3"), ab3);
3063 
3064  v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
3065  CHECK_EQ(100, result->Int32Value());
3066 
3067  result = CompileRun("var u8_b = new Uint8Array(ab3);"
3068  "u8_b[0] = 0xBB;"
3069  "u8_b[1] = 0xCC;"
3070  "u8_b.length");
3071  CHECK_EQ(100, result->Int32Value());
3072  CHECK_EQ(0xBB, my_data[0]);
3073  CHECK_EQ(0xCC, my_data[1]);
3074  my_data[0] = 0xCC;
3075  my_data[1] = 0x11;
3076  result = CompileRun("u8_b[0] + u8_b[1]");
3077  CHECK_EQ(0xDD, result->Int32Value());
3078 }
3079 
3080 
3081 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
3082  CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
3083  CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
3084 }
3085 
3086 
3087 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
3088  CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
3089  CHECK_EQ(0, static_cast<int>(ta->Length()));
3090  CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
3091 }
3092 
3093 
3094 static void CheckIsTypedArrayVarNeutered(const char* name) {
3095  i::ScopedVector<char> source(1024);
3096  i::OS::SNPrintF(source,
3097  "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
3098  name, name, name);
3099  CHECK(CompileRun(source.start())->IsTrue());
3101  v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
3102  CheckIsNeutered(ta);
3103 }
3104 
3105 
3106 template <typename TypedArray, int kElementSize>
3107 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
3108  int byteOffset,
3109  int length) {
3110  v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
3111  CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
3112  CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
3113  CHECK_EQ(length, static_cast<int>(ta->Length()));
3114  CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
3115  return ta;
3116 }
3117 
3118 
3119 THREADED_TEST(ArrayBuffer_NeuteringApi) {
3120  LocalContext env;
3121  v8::Isolate* isolate = env->GetIsolate();
3122  v8::HandleScope handle_scope(isolate);
3123 
3124  v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
3125 
3127  CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
3129  CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
3131  CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
3132 
3134  CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
3136  CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
3137 
3139  CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
3141  CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
3142 
3144  CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
3146  CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
3147 
3148  v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
3149  CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
3150  CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
3151  CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
3152 
3153  ScopedArrayBufferContents contents(buffer->Externalize());
3154  buffer->Neuter();
3155  CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
3156  CheckIsNeutered(u8a);
3157  CheckIsNeutered(u8c);
3158  CheckIsNeutered(i8a);
3159  CheckIsNeutered(u16a);
3160  CheckIsNeutered(i16a);
3161  CheckIsNeutered(u32a);
3162  CheckIsNeutered(i32a);
3163  CheckIsNeutered(f32a);
3164  CheckIsNeutered(f64a);
3165  CheckDataViewIsNeutered(dv);
3166 }
3167 
3168 
3169 THREADED_TEST(ArrayBuffer_NeuteringScript) {
3170  LocalContext env;
3171  v8::Isolate* isolate = env->GetIsolate();
3172  v8::HandleScope handle_scope(isolate);
3173 
3174  CompileRun(
3175  "var ab = new ArrayBuffer(1024);"
3176  "var u8a = new Uint8Array(ab, 1, 1023);"
3177  "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
3178  "var i8a = new Int8Array(ab, 1, 1023);"
3179  "var u16a = new Uint16Array(ab, 2, 511);"
3180  "var i16a = new Int16Array(ab, 2, 511);"
3181  "var u32a = new Uint32Array(ab, 4, 255);"
3182  "var i32a = new Int32Array(ab, 4, 255);"
3183  "var f32a = new Float32Array(ab, 4, 255);"
3184  "var f64a = new Float64Array(ab, 8, 127);"
3185  "var dv = new DataView(ab, 1, 1023);");
3186 
3188  Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
3189 
3191  v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
3192 
3193  ScopedArrayBufferContents contents(ab->Externalize());
3194  ab->Neuter();
3195  CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
3196  CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
3197 
3198  CheckIsTypedArrayVarNeutered("u8a");
3199  CheckIsTypedArrayVarNeutered("u8c");
3200  CheckIsTypedArrayVarNeutered("i8a");
3201  CheckIsTypedArrayVarNeutered("u16a");
3202  CheckIsTypedArrayVarNeutered("i16a");
3203  CheckIsTypedArrayVarNeutered("u32a");
3204  CheckIsTypedArrayVarNeutered("i32a");
3205  CheckIsTypedArrayVarNeutered("f32a");
3206  CheckIsTypedArrayVarNeutered("f64a");
3207 
3208  CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
3209  CheckDataViewIsNeutered(dv);
3210 }
3211 
3212 
3213 
3214 THREADED_TEST(HiddenProperties) {
3215  LocalContext env;
3216  v8::Isolate* isolate = env->GetIsolate();
3217  v8::HandleScope scope(isolate);
3218 
3220  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3221  v8::Local<v8::String> empty = v8_str("");
3222  v8::Local<v8::String> prop_name = v8_str("prop_name");
3223 
3225 
3226  // Make sure delete of a non-existent hidden value works
3227  CHECK(obj->DeleteHiddenValue(key));
3228 
3229  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
3230  CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
3231  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
3232  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3233 
3235 
3236  // Make sure we do not find the hidden property.
3237  CHECK(!obj->Has(empty));
3238  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3239  CHECK(obj->Get(empty)->IsUndefined());
3240  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3241  CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
3242  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3243  CHECK_EQ(2003, obj->Get(empty)->Int32Value());
3244 
3246 
3247  // Add another property and delete it afterwards to force the object in
3248  // slow case.
3249  CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
3250  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3251  CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
3252  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3253  CHECK(obj->Delete(prop_name));
3254  CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
3255 
3257 
3258  CHECK(obj->SetHiddenValue(key, Handle<Value>()));
3259  CHECK(obj->GetHiddenValue(key).IsEmpty());
3260 
3261  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
3262  CHECK(obj->DeleteHiddenValue(key));
3263  CHECK(obj->GetHiddenValue(key).IsEmpty());
3264 }
3265 
3266 
3267 THREADED_TEST(Regress97784) {
3268  // Regression test for crbug.com/97784
3269  // Messing with the Object.prototype should not have effect on
3270  // hidden properties.
3271  LocalContext env;
3272  v8::HandleScope scope(env->GetIsolate());
3273 
3275  v8::Local<v8::String> key = v8_str("hidden");
3276 
3277  CompileRun(
3278  "set_called = false;"
3279  "Object.defineProperty("
3280  " Object.prototype,"
3281  " 'hidden',"
3282  " {get: function() { return 45; },"
3283  " set: function() { set_called = true; }})");
3284 
3285  CHECK(obj->GetHiddenValue(key).IsEmpty());
3286  // Make sure that the getter and setter from Object.prototype is not invoked.
3287  // If it did we would have full access to the hidden properties in
3288  // the accessor.
3289  CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
3290  ExpectFalse("set_called");
3291  CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
3292 }
3293 
3294 
3295 static bool interceptor_for_hidden_properties_called;
3296 static void InterceptorForHiddenProperties(
3297  Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
3298  interceptor_for_hidden_properties_called = true;
3299 }
3300 
3301 
3302 THREADED_TEST(HiddenPropertiesWithInterceptors) {
3303  LocalContext context;
3304  v8::Isolate* isolate = context->GetIsolate();
3305  v8::HandleScope scope(isolate);
3306 
3307  interceptor_for_hidden_properties_called = false;
3308 
3309  v8::Local<v8::String> key = v8_str("api-test::hidden-key");
3310 
3311  // Associate an interceptor with an object and start setting hidden values.
3312  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
3313  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
3314  instance_templ->SetNamedPropertyHandler(InterceptorForHiddenProperties);
3315  Local<v8::Function> function = fun_templ->GetFunction();
3316  Local<v8::Object> obj = function->NewInstance();
3317  CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2302)));
3318  CHECK_EQ(2302, obj->GetHiddenValue(key)->Int32Value());
3319  CHECK(!interceptor_for_hidden_properties_called);
3320 }
3321 
3322 
3323 THREADED_TEST(External) {
3325  int x = 3;
3326  Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
3327  LocalContext env;
3328  env->Global()->Set(v8_str("ext"), ext);
3329  Local<Value> reext_obj = CompileRun("this.ext");
3330  v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
3331  int* ptr = static_cast<int*>(reext->Value());
3332  CHECK_EQ(x, 3);
3333  *ptr = 10;
3334  CHECK_EQ(x, 10);
3335 
3336  // Make sure unaligned pointers are wrapped properly.
3337  char* data = i::StrDup("0123456789");
3338  Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3339  Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3340  Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3341  Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
3342 
3343  char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
3344  CHECK_EQ('0', *char_ptr);
3345  char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
3346  CHECK_EQ('1', *char_ptr);
3347  char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
3348  CHECK_EQ('2', *char_ptr);
3349  char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
3350  CHECK_EQ('3', *char_ptr);
3351  i::DeleteArray(data);
3352 }
3353 
3354 
3355 THREADED_TEST(GlobalHandle) {
3356  v8::Isolate* isolate = CcTest::isolate();
3357  v8::Persistent<String> global;
3358  {
3359  v8::HandleScope scope(isolate);
3360  global.Reset(isolate, v8_str("str"));
3361  }
3362  {
3363  v8::HandleScope scope(isolate);
3364  CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3365  }
3366  global.Reset();
3367  {
3368  v8::HandleScope scope(isolate);
3369  global.Reset(isolate, v8_str("str"));
3370  }
3371  {
3372  v8::HandleScope scope(isolate);
3373  CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3374  }
3375  global.Reset();
3376 }
3377 
3378 
3379 THREADED_TEST(ResettingGlobalHandle) {
3380  v8::Isolate* isolate = CcTest::isolate();
3381  v8::Persistent<String> global;
3382  {
3383  v8::HandleScope scope(isolate);
3384  global.Reset(isolate, v8_str("str"));
3385  }
3386  v8::internal::GlobalHandles* global_handles =
3387  reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3388  int initial_handle_count = global_handles->global_handles_count();
3389  {
3390  v8::HandleScope scope(isolate);
3391  CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3392  }
3393  {
3394  v8::HandleScope scope(isolate);
3395  global.Reset(isolate, v8_str("longer"));
3396  }
3397  CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3398  {
3399  v8::HandleScope scope(isolate);
3400  CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3401  }
3402  global.Reset();
3403  CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3404 }
3405 
3406 
3407 THREADED_TEST(ResettingGlobalHandleToEmpty) {
3408  v8::Isolate* isolate = CcTest::isolate();
3409  v8::Persistent<String> global;
3410  {
3411  v8::HandleScope scope(isolate);
3412  global.Reset(isolate, v8_str("str"));
3413  }
3414  v8::internal::GlobalHandles* global_handles =
3415  reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3416  int initial_handle_count = global_handles->global_handles_count();
3417  {
3418  v8::HandleScope scope(isolate);
3419  CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3420  }
3421  {
3422  v8::HandleScope scope(isolate);
3423  Local<String> empty;
3424  global.Reset(isolate, empty);
3425  }
3426  CHECK(global.IsEmpty());
3427  CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3428 }
3429 
3430 
3431 template<class T>
3432 static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
3433  return unique.Pass();
3434 }
3435 
3436 
3437 template<class T>
3438 static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
3439  const v8::Persistent<T> & global) {
3440  v8::UniquePersistent<String> unique(isolate, global);
3441  return unique.Pass();
3442 }
3443 
3444 
3445 THREADED_TEST(UniquePersistent) {
3446  v8::Isolate* isolate = CcTest::isolate();
3447  v8::Persistent<String> global;
3448  {
3449  v8::HandleScope scope(isolate);
3450  global.Reset(isolate, v8_str("str"));
3451  }
3452  v8::internal::GlobalHandles* global_handles =
3453  reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3454  int initial_handle_count = global_handles->global_handles_count();
3455  {
3456  v8::UniquePersistent<String> unique(isolate, global);
3457  CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3458  // Test assignment via Pass
3459  {
3460  v8::UniquePersistent<String> copy = unique.Pass();
3461  CHECK(unique.IsEmpty());
3462  CHECK(copy == global);
3463  CHECK_EQ(initial_handle_count + 1,
3464  global_handles->global_handles_count());
3465  unique = copy.Pass();
3466  }
3467  // Test ctor via Pass
3468  {
3469  v8::UniquePersistent<String> copy(unique.Pass());
3470  CHECK(unique.IsEmpty());
3471  CHECK(copy == global);
3472  CHECK_EQ(initial_handle_count + 1,
3473  global_handles->global_handles_count());
3474  unique = copy.Pass();
3475  }
3476  // Test pass through function call
3477  {
3478  v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
3479  CHECK(unique.IsEmpty());
3480  CHECK(copy == global);
3481  CHECK_EQ(initial_handle_count + 1,
3482  global_handles->global_handles_count());
3483  unique = copy.Pass();
3484  }
3485  CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3486  }
3487  // Test pass from function call
3488  {
3489  v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
3490  CHECK(unique == global);
3491  CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3492  }
3493  CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3494  global.Reset();
3495 }
3496 
3497 
3498 template<typename K, typename V>
3499 class WeakStdMapTraits : public v8::StdMapTraits<K, V> {
3500  public:
3502  static const bool kIsWeak = true;
3505  K key;
3506  };
3508  Impl* impl, const K& key, Local<V> value) {
3510  data->impl = impl;
3511  data->key = key;
3512  return data;
3513  }
3516  return data.GetParameter()->impl;
3517  }
3520  return data.GetParameter()->key;
3521  }
3523  delete data;
3524  }
3525  static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<V> value,
3526  Impl* impl, K key) { }
3527 };
3528 
3529 
3530 template<typename Map>
3531 static void TestPersistentValueMap() {
3532  LocalContext env;
3533  v8::Isolate* isolate = env->GetIsolate();
3534  Map map(isolate);
3535  v8::internal::GlobalHandles* global_handles =
3536  reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3537  int initial_handle_count = global_handles->global_handles_count();
3538  CHECK_EQ(0, static_cast<int>(map.Size()));
3539  {
3540  HandleScope scope(isolate);
3541  Local<v8::Object> obj = map.Get(7);
3542  CHECK(obj.IsEmpty());
3543  Local<v8::Object> expected = v8::Object::New(isolate);
3544  map.Set(7, expected);
3545  CHECK_EQ(1, static_cast<int>(map.Size()));
3546  obj = map.Get(7);
3547  CHECK_EQ(expected, obj);
3548  v8::UniquePersistent<v8::Object> removed = map.Remove(7);
3549  CHECK_EQ(0, static_cast<int>(map.Size()));
3550  CHECK(expected == removed);
3551  removed = map.Remove(7);
3552  CHECK(removed.IsEmpty());
3553  map.Set(8, expected);
3554  CHECK_EQ(1, static_cast<int>(map.Size()));
3555  map.Set(8, expected);
3556  CHECK_EQ(1, static_cast<int>(map.Size()));
3557  }
3558  CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3559  if (map.IsWeak()) {
3560  reinterpret_cast<v8::internal::Isolate*>(isolate)->heap()->
3561  CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
3562  } else {
3563  map.Clear();
3564  }
3565  CHECK_EQ(0, static_cast<int>(map.Size()));
3566  CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3567 }
3568 
3569 
3570 TEST(PersistentValueMap) {
3571  // Default case, w/o weak callbacks:
3572  TestPersistentValueMap<v8::StdPersistentValueMap<int, v8::Object> >();
3573 
3574  // Custom traits with weak callbacks:
3576  WeakStdMapTraits<int, v8::Object> > WeakPersistentValueMap;
3577  TestPersistentValueMap<WeakPersistentValueMap>();
3578 }
3579 
3580 
3581 THREADED_TEST(GlobalHandleUpcast) {
3582  v8::Isolate* isolate = CcTest::isolate();
3583  v8::HandleScope scope(isolate);
3584  v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
3585  v8::Persistent<String> global_string(isolate, local);
3586  v8::Persistent<Value>& global_value =
3587  v8::Persistent<Value>::Cast(global_string);
3588  CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3589  CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3590  global_string.Reset();
3591 }
3592 
3593 
3594 THREADED_TEST(HandleEquality) {
3595  v8::Isolate* isolate = CcTest::isolate();
3596  v8::Persistent<String> global1;
3597  v8::Persistent<String> global2;
3598  {
3599  v8::HandleScope scope(isolate);
3600  global1.Reset(isolate, v8_str("str"));
3601  global2.Reset(isolate, v8_str("str2"));
3602  }
3603  CHECK_EQ(global1 == global1, true);
3604  CHECK_EQ(global1 != global1, false);
3605  {
3606  v8::HandleScope scope(isolate);
3607  Local<String> local1 = Local<String>::New(isolate, global1);
3608  Local<String> local2 = Local<String>::New(isolate, global2);
3609 
3610  CHECK_EQ(global1 == local1, true);
3611  CHECK_EQ(global1 != local1, false);
3612  CHECK_EQ(local1 == global1, true);
3613  CHECK_EQ(local1 != global1, false);
3614 
3615  CHECK_EQ(global1 == local2, false);
3616  CHECK_EQ(global1 != local2, true);
3617  CHECK_EQ(local2 == global1, false);
3618  CHECK_EQ(local2 != global1, true);
3619 
3620  CHECK_EQ(local1 == local2, false);
3621  CHECK_EQ(local1 != local2, true);
3622 
3623  Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3624  CHECK_EQ(local1 == anotherLocal1, true);
3625  CHECK_EQ(local1 != anotherLocal1, false);
3626  }
3627  global1.Reset();
3628  global2.Reset();
3629 }
3630 
3631 
3632 THREADED_TEST(LocalHandle) {
3634  v8::Local<String> local =
3635  v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
3636  CHECK_EQ(local->Length(), 3);
3637 }
3638 
3639 
3641  public:
3642  explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
3643  int id() { return id_; }
3644  void increment() { number_of_weak_calls_++; }
3645  int NumberOfWeakCalls() { return number_of_weak_calls_; }
3646  private:
3647  int id_;
3648  int number_of_weak_calls_;
3649 };
3650 
3651 
3652 template<typename T>
3655  : counter(counter) {}
3658 };
3659 
3660 
3661 template <typename T>
3662 static void WeakPointerCallback(
3664  CHECK_EQ(1234, data.GetParameter()->counter->id());
3665  data.GetParameter()->counter->increment();
3666  data.GetParameter()->handle.Reset();
3667 }
3668 
3669 
3670 template<typename T>
3671 static UniqueId MakeUniqueId(const Persistent<T>& p) {
3672  return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3673 }
3674 
3675 
3676 THREADED_TEST(ApiObjectGroups) {
3677  LocalContext env;
3678  v8::Isolate* iso = env->GetIsolate();
3679  HandleScope scope(iso);
3680 
3681  WeakCallCounter counter(1234);
3682 
3683  WeakCallCounterAndPersistent<Value> g1s1(&counter);
3684  WeakCallCounterAndPersistent<Value> g1s2(&counter);
3685  WeakCallCounterAndPersistent<Value> g1c1(&counter);
3686  WeakCallCounterAndPersistent<Value> g2s1(&counter);
3687  WeakCallCounterAndPersistent<Value> g2s2(&counter);
3688  WeakCallCounterAndPersistent<Value> g2c1(&counter);
3689 
3690  {
3691  HandleScope scope(iso);
3692  g1s1.handle.Reset(iso, Object::New(iso));
3693  g1s2.handle.Reset(iso, Object::New(iso));
3694  g1c1.handle.Reset(iso, Object::New(iso));
3695  g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3696  g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3697  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3698 
3699  g2s1.handle.Reset(iso, Object::New(iso));
3700  g2s2.handle.Reset(iso, Object::New(iso));
3701  g2c1.handle.Reset(iso, Object::New(iso));
3702  g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3703  g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3704  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3705  }
3706 
3707  WeakCallCounterAndPersistent<Value> root(&counter);
3708  root.handle.Reset(iso, g1s1.handle); // make a root.
3709 
3710  // Connect group 1 and 2, make a cycle.
3711  {
3712  HandleScope scope(iso);
3713  CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())->
3714  Set(0, Local<Value>::New(iso, g2s2.handle)));
3715  CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())->
3716  Set(0, Local<Value>::New(iso, g1s1.handle)));
3717  }
3718 
3719  {
3720  UniqueId id1 = MakeUniqueId(g1s1.handle);
3721  UniqueId id2 = MakeUniqueId(g2s2.handle);
3722  iso->SetObjectGroupId(g1s1.handle, id1);
3723  iso->SetObjectGroupId(g1s2.handle, id1);
3724  iso->SetReferenceFromGroup(id1, g1c1.handle);
3725  iso->SetObjectGroupId(g2s1.handle, id2);
3726  iso->SetObjectGroupId(g2s2.handle, id2);
3727  iso->SetReferenceFromGroup(id2, g2c1.handle);
3728  }
3729  // Do a single full GC, ensure incremental marking is stopped.
3730  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3731  iso)->heap();
3733 
3734  // All object should be alive.
3735  CHECK_EQ(0, counter.NumberOfWeakCalls());
3736 
3737  // Weaken the root.
3738  root.handle.SetWeak(&root, &WeakPointerCallback);
3739  // But make children strong roots---all the objects (except for children)
3740  // should be collectable now.
3741  g1c1.handle.ClearWeak();
3742  g2c1.handle.ClearWeak();
3743 
3744  // Groups are deleted, rebuild groups.
3745  {
3746  UniqueId id1 = MakeUniqueId(g1s1.handle);
3747  UniqueId id2 = MakeUniqueId(g2s2.handle);
3748  iso->SetObjectGroupId(g1s1.handle, id1);
3749  iso->SetObjectGroupId(g1s2.handle, id1);
3750  iso->SetReferenceFromGroup(id1, g1c1.handle);
3751  iso->SetObjectGroupId(g2s1.handle, id2);
3752  iso->SetObjectGroupId(g2s2.handle, id2);
3753  iso->SetReferenceFromGroup(id2, g2c1.handle);
3754  }
3755 
3757 
3758  // All objects should be gone. 5 global handles in total.
3759  CHECK_EQ(5, counter.NumberOfWeakCalls());
3760 
3761  // And now make children weak again and collect them.
3762  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3763  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3764 
3766  CHECK_EQ(7, counter.NumberOfWeakCalls());
3767 }
3768 
3769 
3770 THREADED_TEST(ApiObjectGroupsForSubtypes) {
3771  LocalContext env;
3772  v8::Isolate* iso = env->GetIsolate();
3773  HandleScope scope(iso);
3774 
3775  WeakCallCounter counter(1234);
3776 
3777  WeakCallCounterAndPersistent<Object> g1s1(&counter);
3778  WeakCallCounterAndPersistent<String> g1s2(&counter);
3779  WeakCallCounterAndPersistent<String> g1c1(&counter);
3780  WeakCallCounterAndPersistent<Object> g2s1(&counter);
3781  WeakCallCounterAndPersistent<String> g2s2(&counter);
3782  WeakCallCounterAndPersistent<String> g2c1(&counter);
3783 
3784  {
3785  HandleScope scope(iso);
3786  g1s1.handle.Reset(iso, Object::New(iso));
3787  g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3788  g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3789  g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3790  g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3791  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3792 
3793  g2s1.handle.Reset(iso, Object::New(iso));
3794  g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3795  g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3796  g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3797  g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3798  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3799  }
3800 
3801  WeakCallCounterAndPersistent<Value> root(&counter);
3802  root.handle.Reset(iso, g1s1.handle); // make a root.
3803 
3804  // Connect group 1 and 2, make a cycle.
3805  {
3806  HandleScope scope(iso);
3807  CHECK(Local<Object>::New(iso, g1s1.handle)
3808  ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3809  CHECK(Local<Object>::New(iso, g2s1.handle)
3810  ->Set(0, Local<Object>::New(iso, g1s1.handle)));
3811  }
3812 
3813  {
3814  UniqueId id1 = MakeUniqueId(g1s1.handle);
3815  UniqueId id2 = MakeUniqueId(g2s2.handle);
3816  iso->SetObjectGroupId(g1s1.handle, id1);
3817  iso->SetObjectGroupId(g1s2.handle, id1);
3818  iso->SetReference(g1s1.handle, g1c1.handle);
3819  iso->SetObjectGroupId(g2s1.handle, id2);
3820  iso->SetObjectGroupId(g2s2.handle, id2);
3821  iso->SetReferenceFromGroup(id2, g2c1.handle);
3822  }
3823  // Do a single full GC, ensure incremental marking is stopped.
3824  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3825  iso)->heap();
3827 
3828  // All object should be alive.
3829  CHECK_EQ(0, counter.NumberOfWeakCalls());
3830 
3831  // Weaken the root.
3832  root.handle.SetWeak(&root, &WeakPointerCallback);
3833  // But make children strong roots---all the objects (except for children)
3834  // should be collectable now.
3835  g1c1.handle.ClearWeak();
3836  g2c1.handle.ClearWeak();
3837 
3838  // Groups are deleted, rebuild groups.
3839  {
3840  UniqueId id1 = MakeUniqueId(g1s1.handle);
3841  UniqueId id2 = MakeUniqueId(g2s2.handle);
3842  iso->SetObjectGroupId(g1s1.handle, id1);
3843  iso->SetObjectGroupId(g1s2.handle, id1);
3844  iso->SetReference(g1s1.handle, g1c1.handle);
3845  iso->SetObjectGroupId(g2s1.handle, id2);
3846  iso->SetObjectGroupId(g2s2.handle, id2);
3847  iso->SetReferenceFromGroup(id2, g2c1.handle);
3848  }
3849 
3851 
3852  // All objects should be gone. 5 global handles in total.
3853  CHECK_EQ(5, counter.NumberOfWeakCalls());
3854 
3855  // And now make children weak again and collect them.
3856  g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback);
3857  g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback);
3858 
3860  CHECK_EQ(7, counter.NumberOfWeakCalls());
3861 }
3862 
3863 
3864 THREADED_TEST(ApiObjectGroupsCycle) {
3865  LocalContext env;
3866  v8::Isolate* iso = env->GetIsolate();
3867  HandleScope scope(iso);
3868 
3869  WeakCallCounter counter(1234);
3870 
3871  WeakCallCounterAndPersistent<Value> g1s1(&counter);
3872  WeakCallCounterAndPersistent<Value> g1s2(&counter);
3873  WeakCallCounterAndPersistent<Value> g2s1(&counter);
3874  WeakCallCounterAndPersistent<Value> g2s2(&counter);
3875  WeakCallCounterAndPersistent<Value> g3s1(&counter);
3876  WeakCallCounterAndPersistent<Value> g3s2(&counter);
3877  WeakCallCounterAndPersistent<Value> g4s1(&counter);
3878  WeakCallCounterAndPersistent<Value> g4s2(&counter);
3879 
3880  {
3881  HandleScope scope(iso);
3882  g1s1.handle.Reset(iso, Object::New(iso));
3883  g1s2.handle.Reset(iso, Object::New(iso));
3884  g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3885  g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3886  CHECK(g1s1.handle.IsWeak());
3887  CHECK(g1s2.handle.IsWeak());
3888 
3889  g2s1.handle.Reset(iso, Object::New(iso));
3890  g2s2.handle.Reset(iso, Object::New(iso));
3891  g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
3892  g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
3893  CHECK(g2s1.handle.IsWeak());
3894  CHECK(g2s2.handle.IsWeak());
3895 
3896  g3s1.handle.Reset(iso, Object::New(iso));
3897  g3s2.handle.Reset(iso, Object::New(iso));
3898  g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
3899  g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
3900  CHECK(g3s1.handle.IsWeak());
3901  CHECK(g3s2.handle.IsWeak());
3902 
3903  g4s1.handle.Reset(iso, Object::New(iso));
3904  g4s2.handle.Reset(iso, Object::New(iso));
3905  g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback);
3906  g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback);
3907  CHECK(g4s1.handle.IsWeak());
3908  CHECK(g4s2.handle.IsWeak());
3909  }
3910 
3911  WeakCallCounterAndPersistent<Value> root(&counter);
3912  root.handle.Reset(iso, g1s1.handle); // make a root.
3913 
3914  // Connect groups. We're building the following cycle:
3915  // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3916  // groups.
3917  {
3918  UniqueId id1 = MakeUniqueId(g1s1.handle);
3919  UniqueId id2 = MakeUniqueId(g2s1.handle);
3920  UniqueId id3 = MakeUniqueId(g3s1.handle);
3921  UniqueId id4 = MakeUniqueId(g4s1.handle);
3922  iso->SetObjectGroupId(g1s1.handle, id1);
3923  iso->SetObjectGroupId(g1s2.handle, id1);
3924  iso->SetReferenceFromGroup(id1, g2s1.handle);
3925  iso->SetObjectGroupId(g2s1.handle, id2);
3926  iso->SetObjectGroupId(g2s2.handle, id2);
3927  iso->SetReferenceFromGroup(id2, g3s1.handle);
3928  iso->SetObjectGroupId(g3s1.handle, id3);
3929  iso->SetObjectGroupId(g3s2.handle, id3);
3930  iso->SetReferenceFromGroup(id3, g4s1.handle);
3931  iso->SetObjectGroupId(g4s1.handle, id4);
3932  iso->SetObjectGroupId(g4s2.handle, id4);
3933  iso->SetReferenceFromGroup(id4, g1s1.handle);
3934  }
3935  // Do a single full GC
3936  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
3937  iso)->heap();
3939 
3940  // All object should be alive.
3941  CHECK_EQ(0, counter.NumberOfWeakCalls());
3942 
3943  // Weaken the root.
3944  root.handle.SetWeak(&root, &WeakPointerCallback);
3945 
3946  // Groups are deleted, rebuild groups.
3947  {
3948  UniqueId id1 = MakeUniqueId(g1s1.handle);
3949  UniqueId id2 = MakeUniqueId(g2s1.handle);
3950  UniqueId id3 = MakeUniqueId(g3s1.handle);
3951  UniqueId id4 = MakeUniqueId(g4s1.handle);
3952  iso->SetObjectGroupId(g1s1.handle, id1);
3953  iso->SetObjectGroupId(g1s2.handle, id1);
3954  iso->SetReferenceFromGroup(id1, g2s1.handle);
3955  iso->SetObjectGroupId(g2s1.handle, id2);
3956  iso->SetObjectGroupId(g2s2.handle, id2);
3957  iso->SetReferenceFromGroup(id2, g3s1.handle);
3958  iso->SetObjectGroupId(g3s1.handle, id3);
3959  iso->SetObjectGroupId(g3s2.handle, id3);
3960  iso->SetReferenceFromGroup(id3, g4s1.handle);
3961  iso->SetObjectGroupId(g4s1.handle, id4);
3962  iso->SetObjectGroupId(g4s2.handle, id4);
3963  iso->SetReferenceFromGroup(id4, g1s1.handle);
3964  }
3965 
3967 
3968  // All objects should be gone. 9 global handles in total.
3969  CHECK_EQ(9, counter.NumberOfWeakCalls());
3970 }
3971 
3972 
3973 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3974 // on the buildbots, so was made non-threaded for the time being.
3975 TEST(ApiObjectGroupsCycleForScavenger) {
3976  i::FLAG_stress_compaction = false;
3977  i::FLAG_gc_global = false;
3978  LocalContext env;
3979  v8::Isolate* iso = env->GetIsolate();
3980  HandleScope scope(iso);
3981 
3982  WeakCallCounter counter(1234);
3983 
3984  WeakCallCounterAndPersistent<Value> g1s1(&counter);
3985  WeakCallCounterAndPersistent<Value> g1s2(&counter);
3986  WeakCallCounterAndPersistent<Value> g2s1(&counter);
3987  WeakCallCounterAndPersistent<Value> g2s2(&counter);
3988  WeakCallCounterAndPersistent<Value> g3s1(&counter);
3989  WeakCallCounterAndPersistent<Value> g3s2(&counter);
3990 
3991  {
3992  HandleScope scope(iso);
3993  g1s1.handle.Reset(iso, Object::New(iso));
3994  g1s2.handle.Reset(iso, Object::New(iso));
3995  g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback);
3996  g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback);
3997 
3998  g2s1.handle.Reset(iso, Object::New(iso));
3999  g2s2.handle.Reset(iso, Object::New(iso));
4000  g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback);
4001  g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback);
4002 
4003  g3s1.handle.Reset(iso, Object::New(iso));
4004  g3s2.handle.Reset(iso, Object::New(iso));
4005  g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback);
4006  g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback);
4007  }
4008 
4009  // Make a root.
4010  WeakCallCounterAndPersistent<Value> root(&counter);
4011  root.handle.Reset(iso, g1s1.handle);
4012  root.handle.MarkPartiallyDependent();
4013 
4014  // Connect groups. We're building the following cycle:
4015  // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
4016  // groups.
4017  {
4018  HandleScope handle_scope(iso);
4019  g1s1.handle.MarkPartiallyDependent();
4020  g1s2.handle.MarkPartiallyDependent();
4021  g2s1.handle.MarkPartiallyDependent();
4022  g2s2.handle.MarkPartiallyDependent();
4023  g3s1.handle.MarkPartiallyDependent();
4024  g3s2.handle.MarkPartiallyDependent();
4025  iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4026  iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
4027  Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
4028  v8_str("x"), Local<Value>::New(iso, g2s1.handle));
4029  iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4030  iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
4031  Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
4032  v8_str("x"), Local<Value>::New(iso, g3s1.handle));
4033  iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4034  iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
4035  Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
4036  v8_str("x"), Local<Value>::New(iso, g1s1.handle));
4037  }
4038 
4039  v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
4040  iso)->heap();
4042 
4043  // All objects should be alive.
4044  CHECK_EQ(0, counter.NumberOfWeakCalls());
4045 
4046  // Weaken the root.
4047  root.handle.SetWeak(&root, &WeakPointerCallback);
4048  root.handle.MarkPartiallyDependent();
4049 
4050  // Groups are deleted, rebuild groups.
4051  {
4052  HandleScope handle_scope(iso);
4053  g1s1.handle.MarkPartiallyDependent();
4054  g1s2.handle.MarkPartiallyDependent();
4055  g2s1.handle.MarkPartiallyDependent();
4056  g2s2.handle.MarkPartiallyDependent();
4057  g3s1.handle.MarkPartiallyDependent();
4058  g3s2.handle.MarkPartiallyDependent();
4059  iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
4060  iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
4061  Local<Object>::New(iso, g1s1.handle.As<Object>())->Set(
4062  v8_str("x"), Local<Value>::New(iso, g2s1.handle));
4063  iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
4064  iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
4065  Local<Object>::New(iso, g2s1.handle.As<Object>())->Set(
4066  v8_str("x"), Local<Value>::New(iso, g3s1.handle));
4067  iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
4068  iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
4069  Local<Object>::New(iso, g3s1.handle.As<Object>())->Set(
4070  v8_str("x"), Local<Value>::New(iso, g1s1.handle));
4071  }
4072 
4074 
4075  // All objects should be gone. 7 global handles in total.
4076  CHECK_EQ(7, counter.NumberOfWeakCalls());
4077 }
4078 
4079 
4080 THREADED_TEST(ScriptException) {
4081  LocalContext env;
4082  v8::HandleScope scope(env->GetIsolate());
4083  Local<Script> script = v8_compile("throw 'panama!';");
4084  v8::TryCatch try_catch;
4085  Local<Value> result = script->Run();
4086  CHECK(result.IsEmpty());
4087  CHECK(try_catch.HasCaught());
4088  String::Utf8Value exception_value(try_catch.Exception());
4089  CHECK_EQ(*exception_value, "panama!");
4090 }
4091 
4092 
4093 TEST(TryCatchCustomException) {
4094  LocalContext env;
4095  v8::HandleScope scope(env->GetIsolate());
4096  v8::TryCatch try_catch;
4097  CompileRun("function CustomError() { this.a = 'b'; }"
4098  "(function f() { throw new CustomError(); })();");
4099  CHECK(try_catch.HasCaught());
4100  CHECK(try_catch.Exception()->ToObject()->
4101  Get(v8_str("a"))->Equals(v8_str("b")));
4102 }
4103 
4104 
4106 
4107 
4108 static void check_message_0(v8::Handle<v8::Message> message,
4109  v8::Handle<Value> data) {
4110  CHECK_EQ(5.76, data->NumberValue());
4111  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4112  CHECK(!message->IsSharedCrossOrigin());
4113  message_received = true;
4114 }
4115 
4116 
4117 THREADED_TEST(MessageHandler0) {
4118  message_received = false;
4120  CHECK(!message_received);
4121  LocalContext context;
4122  v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
4123  v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4124  script->Run();
4125  CHECK(message_received);
4126  // clear out the message listener
4127  v8::V8::RemoveMessageListeners(check_message_0);
4128 }
4129 
4130 
4131 static void check_message_1(v8::Handle<v8::Message> message,
4132  v8::Handle<Value> data) {
4133  CHECK(data->IsNumber());
4134  CHECK_EQ(1337, data->Int32Value());
4135  CHECK(!message->IsSharedCrossOrigin());
4136  message_received = true;
4137 }
4138 
4139 
4140 TEST(MessageHandler1) {
4141  message_received = false;
4143  CHECK(!message_received);
4144  v8::V8::AddMessageListener(check_message_1);
4145  LocalContext context;
4146  CompileRun("throw 1337;");
4147  CHECK(message_received);
4148  // clear out the message listener
4149  v8::V8::RemoveMessageListeners(check_message_1);
4150 }
4151 
4152 
4153 static void check_message_2(v8::Handle<v8::Message> message,
4154  v8::Handle<Value> data) {
4155  LocalContext context;
4156  CHECK(data->IsObject());
4157  v8::Local<v8::Value> hidden_property =
4158  v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4159  CHECK(v8_str("hidden value")->Equals(hidden_property));
4160  CHECK(!message->IsSharedCrossOrigin());
4161  message_received = true;
4162 }
4163 
4164 
4165 TEST(MessageHandler2) {
4166  message_received = false;
4168  CHECK(!message_received);
4169  v8::V8::AddMessageListener(check_message_2);
4170  LocalContext context;
4171  v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4172  v8::Object::Cast(*error)->SetHiddenValue(v8_str("hidden key"),
4173  v8_str("hidden value"));
4174  context->Global()->Set(v8_str("error"), error);
4175  CompileRun("throw error;");
4176  CHECK(message_received);
4177  // clear out the message listener
4178  v8::V8::RemoveMessageListeners(check_message_2);
4179 }
4180 
4181 
4182 static void check_message_3(v8::Handle<v8::Message> message,
4183  v8::Handle<Value> data) {
4184  CHECK(message->IsSharedCrossOrigin());
4185  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4186  message_received = true;
4187 }
4188 
4189 
4190 TEST(MessageHandler3) {
4191  message_received = false;
4192  v8::Isolate* isolate = CcTest::isolate();
4193  v8::HandleScope scope(isolate);
4194  CHECK(!message_received);
4195  v8::V8::AddMessageListener(check_message_3);
4196  LocalContext context;
4197  v8::ScriptOrigin origin =
4198  v8::ScriptOrigin(v8_str("6.75"),
4199  v8::Integer::New(isolate, 1),
4200  v8::Integer::New(isolate, 2),
4201  v8::True(isolate));
4202  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4203  &origin);
4204  script->Run();
4205  CHECK(message_received);
4206  // clear out the message listener
4207  v8::V8::RemoveMessageListeners(check_message_3);
4208 }
4209 
4210 
4211 static void check_message_4(v8::Handle<v8::Message> message,
4212  v8::Handle<Value> data) {
4213  CHECK(!message->IsSharedCrossOrigin());
4214  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4215  message_received = true;
4216 }
4217 
4218 
4219 TEST(MessageHandler4) {
4220  message_received = false;
4221  v8::Isolate* isolate = CcTest::isolate();
4222  v8::HandleScope scope(isolate);
4223  CHECK(!message_received);
4224  v8::V8::AddMessageListener(check_message_4);
4225  LocalContext context;
4226  v8::ScriptOrigin origin =
4227  v8::ScriptOrigin(v8_str("6.75"),
4228  v8::Integer::New(isolate, 1),
4229  v8::Integer::New(isolate, 2),
4230  v8::False(isolate));
4231  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4232  &origin);
4233  script->Run();
4234  CHECK(message_received);
4235  // clear out the message listener
4236  v8::V8::RemoveMessageListeners(check_message_4);
4237 }
4238 
4239 
4240 static void check_message_5a(v8::Handle<v8::Message> message,
4241  v8::Handle<Value> data) {
4242  CHECK(message->IsSharedCrossOrigin());
4243  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4244  message_received = true;
4245 }
4246 
4247 
4248 static void check_message_5b(v8::Handle<v8::Message> message,
4249  v8::Handle<Value> data) {
4250  CHECK(!message->IsSharedCrossOrigin());
4251  CHECK_EQ(6.75, message->GetScriptResourceName()->NumberValue());
4252  message_received = true;
4253 }
4254 
4255 
4256 TEST(MessageHandler5) {
4257  message_received = false;
4258  v8::Isolate* isolate = CcTest::isolate();
4259  v8::HandleScope scope(isolate);
4260  CHECK(!message_received);
4261  v8::V8::AddMessageListener(check_message_5a);
4262  LocalContext context;
4263  v8::ScriptOrigin origin =
4264  v8::ScriptOrigin(v8_str("6.75"),
4265  v8::Integer::New(isolate, 1),
4266  v8::Integer::New(isolate, 2),
4267  v8::True(isolate));
4268  v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
4269  &origin);
4270  script->Run();
4271  CHECK(message_received);
4272  // clear out the message listener
4273  v8::V8::RemoveMessageListeners(check_message_5a);
4274 
4275  message_received = false;
4276  v8::V8::AddMessageListener(check_message_5b);
4277  origin =
4278  v8::ScriptOrigin(v8_str("6.75"),
4279  v8::Integer::New(isolate, 1),
4280  v8::Integer::New(isolate, 2),
4281  v8::False(isolate));
4282  script = Script::Compile(v8_str("throw 'error'"),
4283  &origin);
4284  script->Run();
4285  CHECK(message_received);
4286  // clear out the message listener
4287  v8::V8::RemoveMessageListeners(check_message_5b);
4288 }
4289 
4290 
4291 THREADED_TEST(GetSetProperty) {
4292  LocalContext context;
4293  v8::Isolate* isolate = context->GetIsolate();
4294  v8::HandleScope scope(isolate);
4295  context->Global()->Set(v8_str("foo"), v8_num(14));
4296  context->Global()->Set(v8_str("12"), v8_num(92));
4297  context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
4298  context->Global()->Set(v8_num(13), v8_num(56));
4299  Local<Value> foo = CompileRun("this.foo");
4300  CHECK_EQ(14, foo->Int32Value());
4301  Local<Value> twelve = CompileRun("this[12]");
4302  CHECK_EQ(92, twelve->Int32Value());
4303  Local<Value> sixteen = CompileRun("this[16]");
4304  CHECK_EQ(32, sixteen->Int32Value());
4305  Local<Value> thirteen = CompileRun("this[13]");
4306  CHECK_EQ(56, thirteen->Int32Value());
4307  CHECK_EQ(92,
4308  context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
4309  CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4310  CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
4311  CHECK_EQ(32,
4312  context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
4313  CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4314  CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
4315  CHECK_EQ(56,
4316  context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
4317  CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4318  CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4319 }
4320 
4321 
4323  LocalContext context;
4324  v8::HandleScope scope(context->GetIsolate());
4325  // none
4326  Local<String> prop = v8_str("none");
4327  context->Global()->Set(prop, v8_num(7));
4328  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4329  // read-only
4330  prop = v8_str("read_only");
4331  context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
4332  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4333  CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
4334  CompileRun("read_only = 9");
4335  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4336  context->Global()->Set(prop, v8_num(10));
4337  CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4338  // dont-delete
4339  prop = v8_str("dont_delete");
4340  context->Global()->Set(prop, v8_num(13), v8::DontDelete);
4341  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4342  CompileRun("delete dont_delete");
4343  CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4344  CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4345  // dont-enum
4346  prop = v8_str("dont_enum");
4347  context->Global()->Set(prop, v8_num(28), v8::DontEnum);
4348  CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4349  // absent
4350  prop = v8_str("absent");
4351  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4352  Local<Value> fake_prop = v8_num(1);
4353  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4354  // exception
4355  TryCatch try_catch;
4356  Local<Value> exception =
4357  CompileRun("({ toString: function() { throw 'exception';} })");
4358  CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4359  CHECK(try_catch.HasCaught());
4360  String::Utf8Value exception_value(try_catch.Exception());
4361  CHECK_EQ("exception", *exception_value);
4362  try_catch.Reset();
4363 }
4364 
4365 
4367  LocalContext context;
4368  v8::HandleScope scope(context->GetIsolate());
4369  Local<v8::Array> array = v8::Array::New(context->GetIsolate());
4370  CHECK_EQ(0, array->Length());
4371  CHECK(array->Get(0)->IsUndefined());
4372  CHECK(!array->Has(0));
4373  CHECK(array->Get(100)->IsUndefined());
4374  CHECK(!array->Has(100));
4375  array->Set(2, v8_num(7));
4376  CHECK_EQ(3, array->Length());
4377  CHECK(!array->Has(0));
4378  CHECK(!array->Has(1));
4379  CHECK(array->Has(2));
4380  CHECK_EQ(7, array->Get(2)->Int32Value());
4381  Local<Value> obj = CompileRun("[1, 2, 3]");
4382  Local<v8::Array> arr = obj.As<v8::Array>();
4383  CHECK_EQ(3, arr->Length());
4384  CHECK_EQ(1, arr->Get(0)->Int32Value());
4385  CHECK_EQ(2, arr->Get(1)->Int32Value());
4386  CHECK_EQ(3, arr->Get(2)->Int32Value());
4387  array = v8::Array::New(context->GetIsolate(), 27);
4388  CHECK_EQ(27, array->Length());
4389  array = v8::Array::New(context->GetIsolate(), -27);
4390  CHECK_EQ(0, array->Length());
4391 }
4392 
4393 
4395  v8::EscapableHandleScope scope(args.GetIsolate());
4397  Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
4398  for (int i = 0; i < args.Length(); i++)
4399  result->Set(i, args[i]);
4400  args.GetReturnValue().Set(scope.Escape(result));
4401 }
4402 
4403 
4404 THREADED_TEST(Vector) {
4405  v8::Isolate* isolate = CcTest::isolate();
4406  v8::HandleScope scope(isolate);
4407  Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
4408  global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
4409  LocalContext context(0, global);
4410 
4411  const char* fun = "f()";
4412  Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
4413  CHECK_EQ(0, a0->Length());
4414 
4415  const char* fun2 = "f(11)";
4416  Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
4417  CHECK_EQ(1, a1->Length());
4418  CHECK_EQ(11, a1->Get(0)->Int32Value());
4419 
4420  const char* fun3 = "f(12, 13)";
4421  Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
4422  CHECK_EQ(2, a2->Length());
4423  CHECK_EQ(12, a2->Get(0)->Int32Value());
4424  CHECK_EQ(13, a2->Get(1)->Int32Value());
4425 
4426  const char* fun4 = "f(14, 15, 16)";
4427  Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
4428  CHECK_EQ(3, a3->Length());
4429  CHECK_EQ(14, a3->Get(0)->Int32Value());
4430  CHECK_EQ(15, a3->Get(1)->Int32Value());
4431  CHECK_EQ(16, a3->Get(2)->Int32Value());
4432 
4433  const char* fun5 = "f(17, 18, 19, 20)";
4434  Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
4435  CHECK_EQ(4, a4->Length());
4436  CHECK_EQ(17, a4->Get(0)->Int32Value());
4437  CHECK_EQ(18, a4->Get(1)->Int32Value());
4438  CHECK_EQ(19, a4->Get(2)->Int32Value());
4439  CHECK_EQ(20, a4->Get(3)->Int32Value());
4440 }
4441 
4442 
4443 THREADED_TEST(FunctionCall) {
4444  LocalContext context;
4445  v8::Isolate* isolate = context->GetIsolate();
4446  v8::HandleScope scope(isolate);
4447  CompileRun(
4448  "function Foo() {"
4449  " var result = [];"
4450  " for (var i = 0; i < arguments.length; i++) {"
4451  " result.push(arguments[i]);"
4452  " }"
4453  " return result;"
4454  "}"
4455  "function ReturnThisSloppy() {"
4456  " return this;"
4457  "}"
4458  "function ReturnThisStrict() {"
4459  " 'use strict';"
4460  " return this;"
4461  "}");
4462  Local<Function> Foo =
4463  Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4464  Local<Function> ReturnThisSloppy =
4465  Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4466  Local<Function> ReturnThisStrict =
4467  Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
4468 
4469  v8::Handle<Value>* args0 = NULL;
4470  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4471  CHECK_EQ(0, a0->Length());
4472 
4473  v8::Handle<Value> args1[] = { v8_num(1.1) };
4474  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4475  CHECK_EQ(1, a1->Length());
4476  CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4477 
4478  v8::Handle<Value> args2[] = { v8_num(2.2),
4479  v8_num(3.3) };
4480  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4481  CHECK_EQ(2, a2->Length());
4482  CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4483  CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4484 
4485  v8::Handle<Value> args3[] = { v8_num(4.4),
4486  v8_num(5.5),
4487  v8_num(6.6) };
4488  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4489  CHECK_EQ(3, a3->Length());
4490  CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4491  CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4492  CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4493 
4494  v8::Handle<Value> args4[] = { v8_num(7.7),
4495  v8_num(8.8),
4496  v8_num(9.9),
4497  v8_num(10.11) };
4498  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4499  CHECK_EQ(4, a4->Length());
4500  CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4501  CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4502  CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4503  CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4504 
4505  Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4506  CHECK(r1->StrictEquals(context->Global()));
4507  Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4508  CHECK(r2->StrictEquals(context->Global()));
4509  Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4510  CHECK(r3->IsNumberObject());
4511  CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4512  Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4513  CHECK(r4->IsStringObject());
4514  CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4515  Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4516  CHECK(r5->IsBooleanObject());
4517  CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4518 
4519  Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4520  CHECK(r6->IsUndefined());
4521  Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4522  CHECK(r7->IsNull());
4523  Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4524  CHECK(r8->StrictEquals(v8_num(42)));
4525  Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4526  CHECK(r9->StrictEquals(v8_str("hello")));
4527  Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4528  CHECK(r10->StrictEquals(v8::True(isolate)));
4529 }
4530 
4531 
4532 THREADED_TEST(ConstructCall) {
4533  LocalContext context;
4534  v8::Isolate* isolate = context->GetIsolate();
4535  v8::HandleScope scope(isolate);
4536  CompileRun(
4537  "function Foo() {"
4538  " var result = [];"
4539  " for (var i = 0; i < arguments.length; i++) {"
4540  " result.push(arguments[i]);"
4541  " }"
4542  " return result;"
4543  "}");
4544  Local<Function> Foo =
4545  Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4546 
4547  v8::Handle<Value>* args0 = NULL;
4548  Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4549  CHECK_EQ(0, a0->Length());
4550 
4551  v8::Handle<Value> args1[] = { v8_num(1.1) };
4552  Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4553  CHECK_EQ(1, a1->Length());
4554  CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4555 
4556  v8::Handle<Value> args2[] = { v8_num(2.2),
4557  v8_num(3.3) };
4558  Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4559  CHECK_EQ(2, a2->Length());
4560  CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4561  CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4562 
4563  v8::Handle<Value> args3[] = { v8_num(4.4),
4564  v8_num(5.5),
4565  v8_num(6.6) };
4566  Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4567  CHECK_EQ(3, a3->Length());
4568  CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4569  CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4570  CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4571 
4572  v8::Handle<Value> args4[] = { v8_num(7.7),
4573  v8_num(8.8),
4574  v8_num(9.9),
4575  v8_num(10.11) };
4576  Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4577  CHECK_EQ(4, a4->Length());
4578  CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4579  CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4580  CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4581  CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4582 }
4583 
4584 
4585 static void CheckUncle(v8::TryCatch* try_catch) {
4586  CHECK(try_catch->HasCaught());
4587  String::Utf8Value str_value(try_catch->Exception());
4588  CHECK_EQ(*str_value, "uncle?");
4589  try_catch->Reset();
4590 }
4591 
4592 
4593 THREADED_TEST(ConversionNumber) {
4594  LocalContext env;
4595  v8::HandleScope scope(env->GetIsolate());
4596  // Very large number.
4597  CompileRun("var obj = Math.pow(2,32) * 1237;");
4598  Local<Value> obj = env->Global()->Get(v8_str("obj"));
4599  CHECK_EQ(5312874545152.0, obj->ToNumber()->Value());
4600  CHECK_EQ(0, obj->ToInt32()->Value());
4601  CHECK(0u == obj->ToUint32()->Value()); // NOLINT - no CHECK_EQ for unsigned.
4602  // Large number.
4603  CompileRun("var obj = -1234567890123;");
4604  obj = env->Global()->Get(v8_str("obj"));
4605  CHECK_EQ(-1234567890123.0, obj->ToNumber()->Value());
4606  CHECK_EQ(-1912276171, obj->ToInt32()->Value());
4607  CHECK(2382691125u == obj->ToUint32()->Value()); // NOLINT
4608  // Small positive integer.
4609  CompileRun("var obj = 42;");
4610  obj = env->Global()->Get(v8_str("obj"));
4611  CHECK_EQ(42.0, obj->ToNumber()->Value());
4612  CHECK_EQ(42, obj->ToInt32()->Value());
4613  CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4614  // Negative integer.
4615  CompileRun("var obj = -37;");
4616  obj = env->Global()->Get(v8_str("obj"));
4617  CHECK_EQ(-37.0, obj->ToNumber()->Value());
4618  CHECK_EQ(-37, obj->ToInt32()->Value());
4619  CHECK(4294967259u == obj->ToUint32()->Value()); // NOLINT
4620  // Positive non-int32 integer.
4621  CompileRun("var obj = 0x81234567;");
4622  obj = env->Global()->Get(v8_str("obj"));
4623  CHECK_EQ(2166572391.0, obj->ToNumber()->Value());
4624  CHECK_EQ(-2128394905, obj->ToInt32()->Value());
4625  CHECK(2166572391u == obj->ToUint32()->Value()); // NOLINT
4626  // Fraction.
4627  CompileRun("var obj = 42.3;");
4628  obj = env->Global()->Get(v8_str("obj"));
4629  CHECK_EQ(42.3, obj->ToNumber()->Value());
4630  CHECK_EQ(42, obj->ToInt32()->Value());
4631  CHECK(42u == obj->ToUint32()->Value()); // NOLINT
4632  // Large negative fraction.
4633  CompileRun("var obj = -5726623061.75;");
4634  obj = env->Global()->Get(v8_str("obj"));
4635  CHECK_EQ(-5726623061.75, obj->ToNumber()->Value());
4636  CHECK_EQ(-1431655765, obj->ToInt32()->Value());
4637  CHECK(2863311531u == obj->ToUint32()->Value()); // NOLINT
4638 }
4639 
4640 
4641 THREADED_TEST(isNumberType) {
4642  LocalContext env;
4643  v8::HandleScope scope(env->GetIsolate());
4644  // Very large number.
4645  CompileRun("var obj = Math.pow(2,32) * 1237;");
4646  Local<Value> obj = env->Global()->Get(v8_str("obj"));
4647  CHECK(!obj->IsInt32());
4648  CHECK(!obj->IsUint32());
4649  // Large negative number.
4650  CompileRun("var obj = -1234567890123;");
4651  obj = env->Global()->Get(v8_str("obj"));
4652  CHECK(!obj->IsInt32());
4653  CHECK(!obj->IsUint32());
4654  // Small positive integer.
4655  CompileRun("var obj = 42;");
4656  obj = env->Global()->Get(v8_str("obj"));
4657  CHECK(obj->IsInt32());
4658  CHECK(obj->IsUint32());
4659  // Negative integer.
4660  CompileRun("var obj = -37;");
4661  obj = env->Global()->Get(v8_str("obj"));
4662  CHECK(obj->IsInt32());
4663  CHECK(!obj->IsUint32());
4664  // Positive non-int32 integer.
4665  CompileRun("var obj = 0x81234567;");
4666  obj = env->Global()->Get(v8_str("obj"));
4667  CHECK(!obj->IsInt32());
4668  CHECK(obj->IsUint32());
4669  // Fraction.
4670  CompileRun("var obj = 42.3;");
4671  obj = env->Global()->Get(v8_str("obj"));
4672  CHECK(!obj->IsInt32());
4673  CHECK(!obj->IsUint32());
4674  // Large negative fraction.
4675  CompileRun("var obj = -5726623061.75;");
4676  obj = env->Global()->Get(v8_str("obj"));
4677  CHECK(!obj->IsInt32());
4678  CHECK(!obj->IsUint32());
4679  // Positive zero
4680  CompileRun("var obj = 0.0;");
4681  obj = env->Global()->Get(v8_str("obj"));
4682  CHECK(obj->IsInt32());
4683  CHECK(obj->IsUint32());
4684  // Positive zero
4685  CompileRun("var obj = -0.0;");
4686  obj = env->Global()->Get(v8_str("obj"));
4687  CHECK(!obj->IsInt32());
4688  CHECK(!obj->IsUint32());
4689 }
4690 
4691 
4692 THREADED_TEST(ConversionException) {
4693  LocalContext env;
4694  v8::Isolate* isolate = env->GetIsolate();
4695  v8::HandleScope scope(isolate);
4696  CompileRun(
4697  "function TestClass() { };"
4698  "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4699  "var obj = new TestClass();");
4700  Local<Value> obj = env->Global()->Get(v8_str("obj"));
4701 
4702  v8::TryCatch try_catch;
4703 
4704  Local<Value> to_string_result = obj->ToString();
4705  CHECK(to_string_result.IsEmpty());
4706  CheckUncle(&try_catch);
4707 
4708  Local<Value> to_number_result = obj->ToNumber();
4709  CHECK(to_number_result.IsEmpty());
4710  CheckUncle(&try_catch);
4711 
4712  Local<Value> to_integer_result = obj->ToInteger();
4713  CHECK(to_integer_result.IsEmpty());
4714  CheckUncle(&try_catch);
4715 
4716  Local<Value> to_uint32_result = obj->ToUint32();
4717  CHECK(to_uint32_result.IsEmpty());
4718  CheckUncle(&try_catch);
4719 
4720  Local<Value> to_int32_result = obj->ToInt32();
4721  CHECK(to_int32_result.IsEmpty());
4722  CheckUncle(&try_catch);
4723 
4724  Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
4725  CHECK(to_object_result.IsEmpty());
4726  CHECK(try_catch.HasCaught());
4727  try_catch.Reset();
4728 
4729  int32_t int32_value = obj->Int32Value();
4730  CHECK_EQ(0, int32_value);
4731  CheckUncle(&try_catch);
4732 
4733  uint32_t uint32_value = obj->Uint32Value();
4734  CHECK_EQ(0, uint32_value);
4735  CheckUncle(&try_catch);
4736 
4737  double number_value = obj->NumberValue();
4738  CHECK_NE(0, std::isnan(number_value));
4739  CheckUncle(&try_catch);
4740 
4741  int64_t integer_value = obj->IntegerValue();
4742  CHECK_EQ(0.0, static_cast<double>(integer_value));
4743  CheckUncle(&try_catch);
4744 }
4745 
4746 
4749  args.GetIsolate()->ThrowException(v8_str("konto"));
4750 }
4751 
4752 
4754  if (args.Length() < 1) {
4755  args.GetReturnValue().Set(false);
4756  return;
4757  }
4758  v8::HandleScope scope(args.GetIsolate());
4759  v8::TryCatch try_catch;
4760  Local<Value> result = CompileRun(args[0]->ToString());
4761  CHECK(!try_catch.HasCaught() || result.IsEmpty());
4762  args.GetReturnValue().Set(try_catch.HasCaught());
4763 }
4764 
4765 
4766 THREADED_TEST(APICatch) {
4767  v8::Isolate* isolate = CcTest::isolate();
4768  v8::HandleScope scope(isolate);
4769  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4770  templ->Set(v8_str("ThrowFromC"),
4772  LocalContext context(0, templ);
4773  CompileRun(
4774  "var thrown = false;"
4775  "try {"
4776  " ThrowFromC();"
4777  "} catch (e) {"
4778  " thrown = true;"
4779  "}");
4780  Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4781  CHECK(thrown->BooleanValue());
4782 }
4783 
4784 
4785 THREADED_TEST(APIThrowTryCatch) {
4786  v8::Isolate* isolate = CcTest::isolate();
4787  v8::HandleScope scope(isolate);
4788  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4789  templ->Set(v8_str("ThrowFromC"),
4791  LocalContext context(0, templ);
4792  v8::TryCatch try_catch;
4793  CompileRun("ThrowFromC();");
4794  CHECK(try_catch.HasCaught());
4795 }
4796 
4797 
4798 // Test that a try-finally block doesn't shadow a try-catch block
4799 // when setting up an external handler.
4800 //
4801 // BUG(271): Some of the exception propagation does not work on the
4802 // ARM simulator because the simulator separates the C++ stack and the
4803 // JS stack. This test therefore fails on the simulator. The test is
4804 // not threaded to allow the threading tests to run on the simulator.
4805 TEST(TryCatchInTryFinally) {
4806  v8::Isolate* isolate = CcTest::isolate();
4807  v8::HandleScope scope(isolate);
4808  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4809  templ->Set(v8_str("CCatcher"),
4811  LocalContext context(0, templ);
4812  Local<Value> result = CompileRun("try {"
4813  " try {"
4814  " CCatcher('throw 7;');"
4815  " } finally {"
4816  " }"
4817  "} catch (e) {"
4818  "}");
4819  CHECK(result->IsTrue());
4820 }
4821 
4822 
4823 static void check_reference_error_message(
4824  v8::Handle<v8::Message> message,
4825  v8::Handle<v8::Value> data) {
4826  const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4827  CHECK(message->Get()->Equals(v8_str(reference_error)));
4828 }
4829 
4830 
4831 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
4833  CHECK(false);
4834 }
4835 
4836 
4837 // Test that overwritten methods are not invoked on uncaught exception
4838 // formatting. However, they are invoked when performing normal error
4839 // string conversions.
4840 TEST(APIThrowMessageOverwrittenToString) {
4841  v8::Isolate* isolate = CcTest::isolate();
4842  v8::HandleScope scope(isolate);
4843  v8::V8::AddMessageListener(check_reference_error_message);
4844  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4845  templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
4846  LocalContext context(NULL, templ);
4847  CompileRun("asdf;");
4848  CompileRun("var limit = {};"
4849  "limit.valueOf = fail;"
4850  "Error.stackTraceLimit = limit;");
4851  CompileRun("asdf");
4852  CompileRun("Array.prototype.pop = fail;");
4853  CompileRun("Object.prototype.hasOwnProperty = fail;");
4854  CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
4855  CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4856  CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
4857  CompileRun("ReferenceError.prototype.toString ="
4858  " function() { return 'Whoops' }");
4859  CompileRun("asdf;");
4860  CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4861  CompileRun("asdf;");
4862  CompileRun("ReferenceError.prototype.constructor = void 0;");
4863  CompileRun("asdf;");
4864  CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4865  CompileRun("asdf;");
4866  CompileRun("ReferenceError.prototype = new Object();");
4867  CompileRun("asdf;");
4868  v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4869  CHECK(string->Equals(v8_str("Whoops")));
4870  CompileRun("ReferenceError.prototype.constructor = new Object();"
4871  "ReferenceError.prototype.constructor.name = 1;"
4872  "Number.prototype.toString = function() { return 'Whoops'; };"
4873  "ReferenceError.prototype.toString = Object.prototype.toString;");
4874  CompileRun("asdf;");
4875  v8::V8::RemoveMessageListeners(check_reference_error_message);
4876 }
4877 
4878 
4879 static void check_custom_error_tostring(
4880  v8::Handle<v8::Message> message,
4881  v8::Handle<v8::Value> data) {
4882  const char* uncaught_error = "Uncaught MyError toString";
4883  CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4884 }
4885 
4886 
4887 TEST(CustomErrorToString) {
4888  LocalContext context;
4889  v8::HandleScope scope(context->GetIsolate());
4890  v8::V8::AddMessageListener(check_custom_error_tostring);
4891  CompileRun(
4892  "function MyError(name, message) { "
4893  " this.name = name; "
4894  " this.message = message; "
4895  "} "
4896  "MyError.prototype = Object.create(Error.prototype); "
4897  "MyError.prototype.toString = function() { "
4898  " return 'MyError toString'; "
4899  "}; "
4900  "throw new MyError('my name', 'my message'); ");
4901  v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4902 }
4903 
4904 
4905 static void check_custom_error_message(
4906  v8::Handle<v8::Message> message,
4907  v8::Handle<v8::Value> data) {
4908  const char* uncaught_error = "Uncaught MyError: my message";
4909  printf("%s\n", *v8::String::Utf8Value(message->Get()));
4910  CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4911 }
4912 
4913 
4914 TEST(CustomErrorMessage) {
4915  LocalContext context;
4916  v8::HandleScope scope(context->GetIsolate());
4917  v8::V8::AddMessageListener(check_custom_error_message);
4918 
4919  // Handlebars.
4920  CompileRun(
4921  "function MyError(msg) { "
4922  " this.name = 'MyError'; "
4923  " this.message = msg; "
4924  "} "
4925  "MyError.prototype = new Error(); "
4926  "throw new MyError('my message'); ");
4927 
4928  // Closure.
4929  CompileRun(
4930  "function MyError(msg) { "
4931  " this.name = 'MyError'; "
4932  " this.message = msg; "
4933  "} "
4934  "inherits = function(childCtor, parentCtor) { "
4935  " function tempCtor() {}; "
4936  " tempCtor.prototype = parentCtor.prototype; "
4937  " childCtor.superClass_ = parentCtor.prototype; "
4938  " childCtor.prototype = new tempCtor(); "
4939  " childCtor.prototype.constructor = childCtor; "
4940  "}; "
4941  "inherits(MyError, Error); "
4942  "throw new MyError('my message'); ");
4943 
4944  // Object.create.
4945  CompileRun(
4946  "function MyError(msg) { "
4947  " this.name = 'MyError'; "
4948  " this.message = msg; "
4949  "} "
4950  "MyError.prototype = Object.create(Error.prototype); "
4951  "throw new MyError('my message'); ");
4952 
4953  v8::V8::RemoveMessageListeners(check_custom_error_message);
4954 }
4955 
4956 
4957 static void receive_message(v8::Handle<v8::Message> message,
4958  v8::Handle<v8::Value> data) {
4959  message->Get();
4960  message_received = true;
4961 }
4962 
4963 
4964 TEST(APIThrowMessage) {
4965  message_received = false;
4966  v8::Isolate* isolate = CcTest::isolate();
4967  v8::HandleScope scope(isolate);
4968  v8::V8::AddMessageListener(receive_message);
4969  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4970  templ->Set(v8_str("ThrowFromC"),
4972  LocalContext context(0, templ);
4973  CompileRun("ThrowFromC();");
4974  CHECK(message_received);
4975  v8::V8::RemoveMessageListeners(receive_message);
4976 }
4977 
4978 
4979 TEST(APIThrowMessageAndVerboseTryCatch) {
4980  message_received = false;
4981  v8::Isolate* isolate = CcTest::isolate();
4982  v8::HandleScope scope(isolate);
4983  v8::V8::AddMessageListener(receive_message);
4984  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4985  templ->Set(v8_str("ThrowFromC"),
4987  LocalContext context(0, templ);
4988  v8::TryCatch try_catch;
4989  try_catch.SetVerbose(true);
4990  Local<Value> result = CompileRun("ThrowFromC();");
4991  CHECK(try_catch.HasCaught());
4992  CHECK(result.IsEmpty());
4993  CHECK(message_received);
4994  v8::V8::RemoveMessageListeners(receive_message);
4995 }
4996 
4997 
4998 TEST(APIStackOverflowAndVerboseTryCatch) {
4999  message_received = false;
5000  LocalContext context;
5001  v8::HandleScope scope(context->GetIsolate());
5002  v8::V8::AddMessageListener(receive_message);
5003  v8::TryCatch try_catch;
5004  try_catch.SetVerbose(true);
5005  Local<Value> result = CompileRun("function foo() { foo(); } foo();");
5006  CHECK(try_catch.HasCaught());
5007  CHECK(result.IsEmpty());
5008  CHECK(message_received);
5009  v8::V8::RemoveMessageListeners(receive_message);
5010 }
5011 
5012 
5013 THREADED_TEST(ExternalScriptException) {
5014  v8::Isolate* isolate = CcTest::isolate();
5015  v8::HandleScope scope(isolate);
5016  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5017  templ->Set(v8_str("ThrowFromC"),
5019  LocalContext context(0, templ);
5020 
5021  v8::TryCatch try_catch;
5022  Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
5023  CHECK(result.IsEmpty());
5024  CHECK(try_catch.HasCaught());
5025  String::Utf8Value exception_value(try_catch.Exception());
5026  CHECK_EQ("konto", *exception_value);
5027 }
5028 
5029 
5030 
5033  CHECK_EQ(4, args.Length());
5034  int count = args[0]->Int32Value();
5035  int cInterval = args[2]->Int32Value();
5036  if (count == 0) {
5037  args.GetIsolate()->ThrowException(v8_str("FromC"));
5038  return;
5039  } else {
5040  Local<v8::Object> global =
5041  args.GetIsolate()->GetCurrentContext()->Global();
5042  Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5043  v8::Handle<Value> argv[] = { v8_num(count - 1),
5044  args[1],
5045  args[2],
5046  args[3] };
5047  if (count % cInterval == 0) {
5048  v8::TryCatch try_catch;
5049  Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
5050  int expected = args[3]->Int32Value();
5051  if (try_catch.HasCaught()) {
5052  CHECK_EQ(expected, count);
5053  CHECK(result.IsEmpty());
5054  CHECK(!CcTest::i_isolate()->has_scheduled_exception());
5055  } else {
5056  CHECK_NE(expected, count);
5057  }
5058  args.GetReturnValue().Set(result);
5059  return;
5060  } else {
5061  args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5062  return;
5063  }
5064  }
5065 }
5066 
5067 
5070  CHECK_EQ(3, args.Length());
5071  bool equality = args[0]->BooleanValue();
5072  int count = args[1]->Int32Value();
5073  int expected = args[2]->Int32Value();
5074  if (equality) {
5075  CHECK_EQ(count, expected);
5076  } else {
5077  CHECK_NE(count, expected);
5078  }
5079 }
5080 
5081 
5082 THREADED_TEST(EvalInTryFinally) {
5083  LocalContext context;
5084  v8::HandleScope scope(context->GetIsolate());
5085  v8::TryCatch try_catch;
5086  CompileRun("(function() {"
5087  " try {"
5088  " eval('asldkf (*&^&*^');"
5089  " } finally {"
5090  " return;"
5091  " }"
5092  "})()");
5093  CHECK(!try_catch.HasCaught());
5094 }
5095 
5096 
5097 // This test works by making a stack of alternating JavaScript and C
5098 // activations. These activations set up exception handlers with regular
5099 // intervals, one interval for C activations and another for JavaScript
5100 // activations. When enough activations have been created an exception is
5101 // thrown and we check that the right activation catches the exception and that
5102 // no other activations do. The right activation is always the topmost one with
5103 // a handler, regardless of whether it is in JavaScript or C.
5104 //
5105 // The notation used to describe a test case looks like this:
5106 //
5107 // *JS[4] *C[3] @JS[2] C[1] JS[0]
5108 //
5109 // Each entry is an activation, either JS or C. The index is the count at that
5110 // level. Stars identify activations with exception handlers, the @ identifies
5111 // the exception handler that should catch the exception.
5112 //
5113 // BUG(271): Some of the exception propagation does not work on the
5114 // ARM simulator because the simulator separates the C++ stack and the
5115 // JS stack. This test therefore fails on the simulator. The test is
5116 // not threaded to allow the threading tests to run on the simulator.
5117 TEST(ExceptionOrder) {
5118  v8::Isolate* isolate = CcTest::isolate();
5119  v8::HandleScope scope(isolate);
5120  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5121  templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
5122  templ->Set(v8_str("CThrowCountDown"),
5124  LocalContext context(0, templ);
5125  CompileRun(
5126  "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5127  " if (count == 0) throw 'FromJS';"
5128  " if (count % jsInterval == 0) {"
5129  " try {"
5130  " var value = CThrowCountDown(count - 1,"
5131  " jsInterval,"
5132  " cInterval,"
5133  " expected);"
5134  " check(false, count, expected);"
5135  " return value;"
5136  " } catch (e) {"
5137  " check(true, count, expected);"
5138  " }"
5139  " } else {"
5140  " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5141  " }"
5142  "}");
5143  Local<Function> fun =
5144  Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5145 
5146  const int argc = 4;
5147  // count jsInterval cInterval expected
5148 
5149  // *JS[4] *C[3] @JS[2] C[1] JS[0]
5150  v8::Handle<Value> a0[argc] = { v8_num(4), v8_num(2), v8_num(3), v8_num(2) };
5151  fun->Call(fun, argc, a0);
5152 
5153  // JS[5] *C[4] JS[3] @C[2] JS[1] C[0]
5154  v8::Handle<Value> a1[argc] = { v8_num(5), v8_num(6), v8_num(1), v8_num(2) };
5155  fun->Call(fun, argc, a1);
5156 
5157  // JS[6] @C[5] JS[4] C[3] JS[2] C[1] JS[0]
5158  v8::Handle<Value> a2[argc] = { v8_num(6), v8_num(7), v8_num(5), v8_num(5) };
5159  fun->Call(fun, argc, a2);
5160 
5161  // @JS[6] C[5] JS[4] C[3] JS[2] C[1] JS[0]
5162  v8::Handle<Value> a3[argc] = { v8_num(6), v8_num(6), v8_num(7), v8_num(6) };
5163  fun->Call(fun, argc, a3);
5164 
5165  // JS[6] *C[5] @JS[4] C[3] JS[2] C[1] JS[0]
5166  v8::Handle<Value> a4[argc] = { v8_num(6), v8_num(4), v8_num(5), v8_num(4) };
5167  fun->Call(fun, argc, a4);
5168 
5169  // JS[6] C[5] *JS[4] @C[3] JS[2] C[1] JS[0]
5170  v8::Handle<Value> a5[argc] = { v8_num(6), v8_num(4), v8_num(3), v8_num(3) };
5171  fun->Call(fun, argc, a5);
5172 }
5173 
5174 
5177  CHECK_EQ(1, args.Length());
5178  args.GetIsolate()->ThrowException(args[0]);
5179 }
5180 
5181 
5182 THREADED_TEST(ThrowValues) {
5183  v8::Isolate* isolate = CcTest::isolate();
5184  v8::HandleScope scope(isolate);
5185  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5186  templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
5187  LocalContext context(0, templ);
5189  "function Run(obj) {"
5190  " try {"
5191  " Throw(obj);"
5192  " } catch (e) {"
5193  " return e;"
5194  " }"
5195  " return 'no exception';"
5196  "}"
5197  "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5198  CHECK_EQ(5, result->Length());
5199  CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5200  CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5201  CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5202  CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5203  CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5204  CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5205  CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
5206 }
5207 
5208 
5209 THREADED_TEST(CatchZero) {
5210  LocalContext context;
5211  v8::HandleScope scope(context->GetIsolate());
5212  v8::TryCatch try_catch;
5213  CHECK(!try_catch.HasCaught());
5214  CompileRun("throw 10");
5215  CHECK(try_catch.HasCaught());
5216  CHECK_EQ(10, try_catch.Exception()->Int32Value());
5217  try_catch.Reset();
5218  CHECK(!try_catch.HasCaught());
5219  CompileRun("throw 0");
5220  CHECK(try_catch.HasCaught());
5221  CHECK_EQ(0, try_catch.Exception()->Int32Value());
5222 }
5223 
5224 
5225 THREADED_TEST(CatchExceptionFromWith) {
5226  LocalContext context;
5227  v8::HandleScope scope(context->GetIsolate());
5228  v8::TryCatch try_catch;
5229  CHECK(!try_catch.HasCaught());
5230  CompileRun("var o = {}; with (o) { throw 42; }");
5231  CHECK(try_catch.HasCaught());
5232 }
5233 
5234 
5235 THREADED_TEST(TryCatchAndFinallyHidingException) {
5236  LocalContext context;
5237  v8::HandleScope scope(context->GetIsolate());
5238  v8::TryCatch try_catch;
5239  CHECK(!try_catch.HasCaught());
5240  CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5241  CompileRun("f({toString: function() { throw 42; }});");
5242  CHECK(!try_catch.HasCaught());
5243 }
5244 
5245 
5247  v8::TryCatch try_catch;
5248 }
5249 
5250 
5251 THREADED_TEST(TryCatchAndFinally) {
5252  LocalContext context;
5253  v8::Isolate* isolate = context->GetIsolate();
5254  v8::HandleScope scope(isolate);
5255  context->Global()->Set(
5256  v8_str("native_with_try_catch"),
5257  v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
5258  v8::TryCatch try_catch;
5259  CHECK(!try_catch.HasCaught());
5260  CompileRun(
5261  "try {\n"
5262  " throw new Error('a');\n"
5263  "} finally {\n"
5264  " native_with_try_catch();\n"
5265  "}\n");
5266  CHECK(try_catch.HasCaught());
5267 }
5268 
5269 
5270 static void TryCatchNestedHelper(int depth) {
5271  if (depth > 0) {
5272  v8::TryCatch try_catch;
5273  try_catch.SetVerbose(true);
5274  TryCatchNestedHelper(depth - 1);
5275  CHECK(try_catch.HasCaught());
5276  try_catch.ReThrow();
5277  } else {
5278  CcTest::isolate()->ThrowException(v8_str("back"));
5279  }
5280 }
5281 
5282 
5283 TEST(TryCatchNested) {
5285  LocalContext context;
5286  v8::HandleScope scope(context->GetIsolate());
5287  v8::TryCatch try_catch;
5288  TryCatchNestedHelper(5);
5289  CHECK(try_catch.HasCaught());
5290  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "back"));
5291 }
5292 
5293 
5295  CHECK(try_catch->HasCaught());
5296  Handle<Message> message = try_catch->Message();
5297  Handle<Value> resource = message->GetScriptResourceName();
5298  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5299  CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
5300  "Uncaught Error: a"));
5301  CHECK_EQ(1, message->GetLineNumber());
5302  CHECK_EQ(6, message->GetStartColumn());
5303 }
5304 
5305 
5309  v8::TryCatch try_catch;
5310  CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5311  CHECK(try_catch.HasCaught());
5312  TryCatchMixedNestingCheck(&try_catch);
5313  try_catch.ReThrow();
5314 }
5315 
5316 
5317 // This test ensures that an outer TryCatch in the following situation:
5318 // C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5319 // does not clobber the Message object generated for the inner TryCatch.
5320 // This exercises the ability of TryCatch.ReThrow() to restore the
5321 // inner pending Message before throwing the exception again.
5322 TEST(TryCatchMixedNesting) {
5323  v8::Isolate* isolate = CcTest::isolate();
5324  v8::HandleScope scope(isolate);
5326  v8::TryCatch try_catch;
5327  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5328  templ->Set(v8_str("TryCatchMixedNestingHelper"),
5330  LocalContext context(0, templ);
5331  CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5332  TryCatchMixedNestingCheck(&try_catch);
5333 }
5334 
5335 
5336 THREADED_TEST(Equality) {
5337  LocalContext context;
5338  v8::Isolate* isolate = context->GetIsolate();
5339  v8::HandleScope scope(context->GetIsolate());
5340  // Check that equality works at all before relying on CHECK_EQ
5341  CHECK(v8_str("a")->Equals(v8_str("a")));
5342  CHECK(!v8_str("a")->Equals(v8_str("b")));
5343 
5344  CHECK_EQ(v8_str("a"), v8_str("a"));
5345  CHECK_NE(v8_str("a"), v8_str("b"));
5346  CHECK_EQ(v8_num(1), v8_num(1));
5347  CHECK_EQ(v8_num(1.00), v8_num(1));
5348  CHECK_NE(v8_num(1), v8_num(2));
5349 
5350  // Assume String is not internalized.
5351  CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5352  CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5353  CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5354  CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5355  CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
5356  CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
5357  Local<Value> not_a_number = v8_num(i::OS::nan_value());
5358  CHECK(!not_a_number->StrictEquals(not_a_number));
5359  CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5360  CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
5361 
5362  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
5363  v8::Persistent<v8::Object> alias(isolate, obj);
5364  CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
5365  alias.Reset();
5366 
5367  CHECK(v8_str("a")->SameValue(v8_str("a")));
5368  CHECK(!v8_str("a")->SameValue(v8_str("b")));
5369  CHECK(!v8_str("5")->SameValue(v8_num(5)));
5370  CHECK(v8_num(1)->SameValue(v8_num(1)));
5371  CHECK(!v8_num(1)->SameValue(v8_num(2)));
5372  CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5373  CHECK(not_a_number->SameValue(not_a_number));
5374  CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5375  CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
5376 }
5377 
5378 
5379 THREADED_TEST(MultiRun) {
5380  LocalContext context;
5381  v8::HandleScope scope(context->GetIsolate());
5382  Local<Script> script = v8_compile("x");
5383  for (int i = 0; i < 10; i++)
5384  script->Run();
5385 }
5386 
5387 
5388 static void GetXValue(Local<String> name,
5391  CHECK_EQ(info.Data(), v8_str("donut"));
5392  CHECK_EQ(name, v8_str("x"));
5393  info.GetReturnValue().Set(name);
5394 }
5395 
5396 
5397 THREADED_TEST(SimplePropertyRead) {
5398  LocalContext context;
5399  v8::Isolate* isolate = context->GetIsolate();
5400  v8::HandleScope scope(isolate);
5401  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5402  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5403  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5404  Local<Script> script = v8_compile("obj.x");
5405  for (int i = 0; i < 10; i++) {
5406  Local<Value> result = script->Run();
5407  CHECK_EQ(result, v8_str("x"));
5408  }
5409 }
5410 
5411 
5412 THREADED_TEST(DefinePropertyOnAPIAccessor) {
5413  LocalContext context;
5414  v8::Isolate* isolate = context->GetIsolate();
5415  v8::HandleScope scope(isolate);
5416  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5417  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5418  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5419 
5420  // Uses getOwnPropertyDescriptor to check the configurable status
5421  Local<Script> script_desc = v8_compile(
5422  "var prop = Object.getOwnPropertyDescriptor( "
5423  "obj, 'x');"
5424  "prop.configurable;");
5425  Local<Value> result = script_desc->Run();
5426  CHECK_EQ(result->BooleanValue(), true);
5427 
5428  // Redefine get - but still configurable
5429  Local<Script> script_define = v8_compile(
5430  "var desc = { get: function(){return 42; },"
5431  " configurable: true };"
5432  "Object.defineProperty(obj, 'x', desc);"
5433  "obj.x");
5434  result = script_define->Run();
5435  CHECK_EQ(result, v8_num(42));
5436 
5437  // Check that the accessor is still configurable
5438  result = script_desc->Run();
5439  CHECK_EQ(result->BooleanValue(), true);
5440 
5441  // Redefine to a non-configurable
5442  script_define = v8_compile(
5443  "var desc = { get: function(){return 43; },"
5444  " configurable: false };"
5445  "Object.defineProperty(obj, 'x', desc);"
5446  "obj.x");
5447  result = script_define->Run();
5448  CHECK_EQ(result, v8_num(43));
5449  result = script_desc->Run();
5450  CHECK_EQ(result->BooleanValue(), false);
5451 
5452  // Make sure that it is not possible to redefine again
5453  v8::TryCatch try_catch;
5454  result = script_define->Run();
5455  CHECK(try_catch.HasCaught());
5456  String::Utf8Value exception_value(try_catch.Exception());
5457  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5458 }
5459 
5460 
5461 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
5462  v8::Isolate* isolate = CcTest::isolate();
5463  v8::HandleScope scope(isolate);
5464  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5465  templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5466  LocalContext context;
5467  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5468 
5469  Local<Script> script_desc = v8_compile(
5470  "var prop ="
5471  "Object.getOwnPropertyDescriptor( "
5472  "obj, 'x');"
5473  "prop.configurable;");
5474  Local<Value> result = script_desc->Run();
5475  CHECK_EQ(result->BooleanValue(), true);
5476 
5477  Local<Script> script_define = v8_compile(
5478  "var desc = {get: function(){return 42; },"
5479  " configurable: true };"
5480  "Object.defineProperty(obj, 'x', desc);"
5481  "obj.x");
5482  result = script_define->Run();
5483  CHECK_EQ(result, v8_num(42));
5484 
5485 
5486  result = script_desc->Run();
5487  CHECK_EQ(result->BooleanValue(), true);
5488 
5489 
5490  script_define = v8_compile(
5491  "var desc = {get: function(){return 43; },"
5492  " configurable: false };"
5493  "Object.defineProperty(obj, 'x', desc);"
5494  "obj.x");
5495  result = script_define->Run();
5496  CHECK_EQ(result, v8_num(43));
5497  result = script_desc->Run();
5498 
5499  CHECK_EQ(result->BooleanValue(), false);
5500 
5501  v8::TryCatch try_catch;
5502  result = script_define->Run();
5503  CHECK(try_catch.HasCaught());
5504  String::Utf8Value exception_value(try_catch.Exception());
5505  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5506 }
5507 
5508 
5509 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5510  char const* name) {
5511  return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5512 }
5513 
5514 
5515 THREADED_TEST(DefineAPIAccessorOnObject) {
5516  v8::Isolate* isolate = CcTest::isolate();
5517  v8::HandleScope scope(isolate);
5518  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5519  LocalContext context;
5520 
5521  context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5522  CompileRun("var obj2 = {};");
5523 
5524  CHECK(CompileRun("obj1.x")->IsUndefined());
5525  CHECK(CompileRun("obj2.x")->IsUndefined());
5526 
5527  CHECK(GetGlobalProperty(&context, "obj1")->
5528  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5529 
5530  ExpectString("obj1.x", "x");
5531  CHECK(CompileRun("obj2.x")->IsUndefined());
5532 
5533  CHECK(GetGlobalProperty(&context, "obj2")->
5534  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5535 
5536  ExpectString("obj1.x", "x");
5537  ExpectString("obj2.x", "x");
5538 
5539  ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5540  ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5541 
5542  CompileRun("Object.defineProperty(obj1, 'x',"
5543  "{ get: function() { return 'y'; }, configurable: true })");
5544 
5545  ExpectString("obj1.x", "y");
5546  ExpectString("obj2.x", "x");
5547 
5548  CompileRun("Object.defineProperty(obj2, 'x',"
5549  "{ get: function() { return 'y'; }, configurable: true })");
5550 
5551  ExpectString("obj1.x", "y");
5552  ExpectString("obj2.x", "y");
5553 
5554  ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5555  ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5556 
5557  CHECK(GetGlobalProperty(&context, "obj1")->
5558  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5559  CHECK(GetGlobalProperty(&context, "obj2")->
5560  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5561 
5562  ExpectString("obj1.x", "x");
5563  ExpectString("obj2.x", "x");
5564 
5565  ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5566  ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5567 
5568  // Define getters/setters, but now make them not configurable.
5569  CompileRun("Object.defineProperty(obj1, 'x',"
5570  "{ get: function() { return 'z'; }, configurable: false })");
5571  CompileRun("Object.defineProperty(obj2, 'x',"
5572  "{ get: function() { return 'z'; }, configurable: false })");
5573 
5574  ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5575  ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5576 
5577  ExpectString("obj1.x", "z");
5578  ExpectString("obj2.x", "z");
5579 
5580  CHECK(!GetGlobalProperty(&context, "obj1")->
5581  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5582  CHECK(!GetGlobalProperty(&context, "obj2")->
5583  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5584 
5585  ExpectString("obj1.x", "z");
5586  ExpectString("obj2.x", "z");
5587 }
5588 
5589 
5590 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
5591  v8::Isolate* isolate = CcTest::isolate();
5592  v8::HandleScope scope(isolate);
5593  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5594  LocalContext context;
5595 
5596  context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5597  CompileRun("var obj2 = {};");
5598 
5599  CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5600  v8_str("x"),
5601  GetXValue, NULL,
5602  v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5603  CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5604  v8_str("x"),
5605  GetXValue, NULL,
5606  v8_str("donut"), v8::DEFAULT, v8::DontDelete));
5607 
5608  ExpectString("obj1.x", "x");
5609  ExpectString("obj2.x", "x");
5610 
5611  ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5612  ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5613 
5614  CHECK(!GetGlobalProperty(&context, "obj1")->
5615  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5616  CHECK(!GetGlobalProperty(&context, "obj2")->
5617  SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5618 
5619  {
5620  v8::TryCatch try_catch;
5621  CompileRun("Object.defineProperty(obj1, 'x',"
5622  "{get: function() { return 'func'; }})");
5623  CHECK(try_catch.HasCaught());
5624  String::Utf8Value exception_value(try_catch.Exception());
5625  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5626  }
5627  {
5628  v8::TryCatch try_catch;
5629  CompileRun("Object.defineProperty(obj2, 'x',"
5630  "{get: function() { return 'func'; }})");
5631  CHECK(try_catch.HasCaught());
5632  String::Utf8Value exception_value(try_catch.Exception());
5633  CHECK_EQ(*exception_value, "TypeError: Cannot redefine property: x");
5634  }
5635 }
5636 
5637 
5638 static void Get239Value(Local<String> name,
5641  CHECK_EQ(info.Data(), v8_str("donut"));
5642  CHECK_EQ(name, v8_str("239"));
5643  info.GetReturnValue().Set(name);
5644 }
5645 
5646 
5647 THREADED_TEST(ElementAPIAccessor) {
5648  v8::Isolate* isolate = CcTest::isolate();
5649  v8::HandleScope scope(isolate);
5650  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5651  LocalContext context;
5652 
5653  context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5654  CompileRun("var obj2 = {};");
5655 
5656  CHECK(GetGlobalProperty(&context, "obj1")->SetAccessor(
5657  v8_str("239"),
5658  Get239Value, NULL,
5659  v8_str("donut")));
5660  CHECK(GetGlobalProperty(&context, "obj2")->SetAccessor(
5661  v8_str("239"),
5662  Get239Value, NULL,
5663  v8_str("donut")));
5664 
5665  ExpectString("obj1[239]", "239");
5666  ExpectString("obj2[239]", "239");
5667  ExpectString("obj1['239']", "239");
5668  ExpectString("obj2['239']", "239");
5669 }
5670 
5671 
5673 
5674 
5675 static void SetXValue(Local<String> name,
5676  Local<Value> value,
5677  const v8::PropertyCallbackInfo<void>& info) {
5678  CHECK_EQ(value, v8_num(4));
5679  CHECK_EQ(info.Data(), v8_str("donut"));
5680  CHECK_EQ(name, v8_str("x"));
5681  CHECK(xValue.IsEmpty());
5682  xValue.Reset(info.GetIsolate(), value);
5683 }
5684 
5685 
5686 THREADED_TEST(SimplePropertyWrite) {
5687  v8::Isolate* isolate = CcTest::isolate();
5688  v8::HandleScope scope(isolate);
5689  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5690  templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5691  LocalContext context;
5692  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5693  Local<Script> script = v8_compile("obj.x = 4");
5694  for (int i = 0; i < 10; i++) {
5695  CHECK(xValue.IsEmpty());
5696  script->Run();
5697  CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
5698  xValue.Reset();
5699  }
5700 }
5701 
5702 
5703 THREADED_TEST(SetterOnly) {
5704  v8::Isolate* isolate = CcTest::isolate();
5705  v8::HandleScope scope(isolate);
5706  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5707  templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5708  LocalContext context;
5709  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5710  Local<Script> script = v8_compile("obj.x = 4; obj.x");
5711  for (int i = 0; i < 10; i++) {
5712  CHECK(xValue.IsEmpty());
5713  script->Run();
5714  CHECK_EQ(v8_num(4), Local<Value>::New(CcTest::isolate(), xValue));
5715  xValue.Reset();
5716  }
5717 }
5718 
5719 
5720 THREADED_TEST(NoAccessors) {
5721  v8::Isolate* isolate = CcTest::isolate();
5722  v8::HandleScope scope(isolate);
5723  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5724  templ->SetAccessor(v8_str("x"),
5725  static_cast<v8::AccessorGetterCallback>(NULL),
5726  NULL,
5727  v8_str("donut"));
5728  LocalContext context;
5729  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5730  Local<Script> script = v8_compile("obj.x = 4; obj.x");
5731  for (int i = 0; i < 10; i++) {
5732  script->Run();
5733  }
5734 }
5735 
5736 
5737 static void XPropertyGetter(Local<String> property,
5740  CHECK(info.Data()->IsUndefined());
5741  info.GetReturnValue().Set(property);
5742 }
5743 
5744 
5745 THREADED_TEST(NamedInterceptorPropertyRead) {
5746  v8::Isolate* isolate = CcTest::isolate();
5747  v8::HandleScope scope(isolate);
5748  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5749  templ->SetNamedPropertyHandler(XPropertyGetter);
5750  LocalContext context;
5751  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5752  Local<Script> script = v8_compile("obj.x");
5753  for (int i = 0; i < 10; i++) {
5754  Local<Value> result = script->Run();
5755  CHECK_EQ(result, v8_str("x"));
5756  }
5757 }
5758 
5759 
5760 THREADED_TEST(NamedInterceptorDictionaryIC) {
5761  v8::Isolate* isolate = CcTest::isolate();
5762  v8::HandleScope scope(isolate);
5763  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5764  templ->SetNamedPropertyHandler(XPropertyGetter);
5765  LocalContext context;
5766  // Create an object with a named interceptor.
5767  context->Global()->Set(v8_str("interceptor_obj"), templ->NewInstance());
5768  Local<Script> script = v8_compile("interceptor_obj.x");
5769  for (int i = 0; i < 10; i++) {
5770  Local<Value> result = script->Run();
5771  CHECK_EQ(result, v8_str("x"));
5772  }
5773  // Create a slow case object and a function accessing a property in
5774  // that slow case object (with dictionary probing in generated
5775  // code). Then force object with a named interceptor into slow-case,
5776  // pass it to the function, and check that the interceptor is called
5777  // instead of accessing the local property.
5778  Local<Value> result =
5779  CompileRun("function get_x(o) { return o.x; };"
5780  "var obj = { x : 42, y : 0 };"
5781  "delete obj.y;"
5782  "for (var i = 0; i < 10; i++) get_x(obj);"
5783  "interceptor_obj.x = 42;"
5784  "interceptor_obj.y = 10;"
5785  "delete interceptor_obj.y;"
5786  "get_x(interceptor_obj)");
5787  CHECK_EQ(result, v8_str("x"));
5788 }
5789 
5790 
5791 THREADED_TEST(NamedInterceptorDictionaryICMultipleContext) {
5792  v8::Isolate* isolate = CcTest::isolate();
5793  v8::HandleScope scope(isolate);
5794  v8::Local<Context> context1 = Context::New(isolate);
5795 
5796  context1->Enter();
5797  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5798  templ->SetNamedPropertyHandler(XPropertyGetter);
5799  // Create an object with a named interceptor.
5800  v8::Local<v8::Object> object = templ->NewInstance();
5801  context1->Global()->Set(v8_str("interceptor_obj"), object);
5802 
5803  // Force the object into the slow case.
5804  CompileRun("interceptor_obj.y = 0;"
5805  "delete interceptor_obj.y;");
5806  context1->Exit();
5807 
5808  {
5809  // Introduce the object into a different context.
5810  // Repeat named loads to exercise ICs.
5811  LocalContext context2;
5812  context2->Global()->Set(v8_str("interceptor_obj"), object);
5813  Local<Value> result =
5814  CompileRun("function get_x(o) { return o.x; }"
5815  "interceptor_obj.x = 42;"
5816  "for (var i=0; i != 10; i++) {"
5817  " get_x(interceptor_obj);"
5818  "}"
5819  "get_x(interceptor_obj)");
5820  // Check that the interceptor was actually invoked.
5821  CHECK_EQ(result, v8_str("x"));
5822  }
5823 
5824  // Return to the original context and force some object to the slow case
5825  // to cause the NormalizedMapCache to verify.
5826  context1->Enter();
5827  CompileRun("var obj = { x : 0 }; delete obj.x;");
5828  context1->Exit();
5829 }
5830 
5831 
5832 static void SetXOnPrototypeGetter(
5833  Local<String> property,
5835  // Set x on the prototype object and do not handle the get request.
5836  v8::Handle<v8::Value> proto = info.Holder()->GetPrototype();
5837  proto.As<v8::Object>()->Set(v8_str("x"),
5838  v8::Integer::New(info.GetIsolate(), 23));
5839 }
5840 
5841 
5842 // This is a regression test for http://crbug.com/20104. Map
5843 // transitions should not interfere with post interceptor lookup.
5844 THREADED_TEST(NamedInterceptorMapTransitionRead) {
5845  v8::Isolate* isolate = CcTest::isolate();
5846  v8::HandleScope scope(isolate);
5847  Local<v8::FunctionTemplate> function_template =
5848  v8::FunctionTemplate::New(isolate);
5849  Local<v8::ObjectTemplate> instance_template
5850  = function_template->InstanceTemplate();
5851  instance_template->SetNamedPropertyHandler(SetXOnPrototypeGetter);
5852  LocalContext context;
5853  context->Global()->Set(v8_str("F"), function_template->GetFunction());
5854  // Create an instance of F and introduce a map transition for x.
5855  CompileRun("var o = new F(); o.x = 23;");
5856  // Create an instance of F and invoke the getter. The result should be 23.
5857  Local<Value> result = CompileRun("o = new F(); o.x");
5858  CHECK_EQ(result->Int32Value(), 23);
5859 }
5860 
5861 
5862 static void IndexedPropertyGetter(
5863  uint32_t index,
5866  if (index == 37) {
5867  info.GetReturnValue().Set(v8_num(625));
5868  }
5869 }
5870 
5871 
5872 static void IndexedPropertySetter(
5873  uint32_t index,
5874  Local<Value> value,
5877  if (index == 39) {
5878  info.GetReturnValue().Set(value);
5879  }
5880 }
5881 
5882 
5883 THREADED_TEST(IndexedInterceptorWithIndexedAccessor) {
5884  v8::Isolate* isolate = CcTest::isolate();
5885  v8::HandleScope scope(isolate);
5886  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5887  templ->SetIndexedPropertyHandler(IndexedPropertyGetter,
5888  IndexedPropertySetter);
5889  LocalContext context;
5890  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5891  Local<Script> getter_script = v8_compile(
5892  "obj.__defineGetter__(\"3\", function(){return 5;});obj[3];");
5893  Local<Script> setter_script = v8_compile(
5894  "obj.__defineSetter__(\"17\", function(val){this.foo = val;});"
5895  "obj[17] = 23;"
5896  "obj.foo;");
5897  Local<Script> interceptor_setter_script = v8_compile(
5898  "obj.__defineSetter__(\"39\", function(val){this.foo = \"hit\";});"
5899  "obj[39] = 47;"
5900  "obj.foo;"); // This setter should not run, due to the interceptor.
5901  Local<Script> interceptor_getter_script = v8_compile(
5902  "obj[37];");
5903  Local<Value> result = getter_script->Run();
5904  CHECK_EQ(v8_num(5), result);
5905  result = setter_script->Run();
5906  CHECK_EQ(v8_num(23), result);
5907  result = interceptor_setter_script->Run();
5908  CHECK_EQ(v8_num(23), result);
5909  result = interceptor_getter_script->Run();
5910  CHECK_EQ(v8_num(625), result);
5911 }
5912 
5913 
5914 static void UnboxedDoubleIndexedPropertyGetter(
5915  uint32_t index,
5918  if (index < 25) {
5919  info.GetReturnValue().Set(v8_num(index));
5920  }
5921 }
5922 
5923 
5924 static void UnboxedDoubleIndexedPropertySetter(
5925  uint32_t index,
5926  Local<Value> value,
5929  if (index < 25) {
5930  info.GetReturnValue().Set(v8_num(index));
5931  }
5932 }
5933 
5934 
5937  // Force the list of returned keys to be stored in a FastDoubleArray.
5938  Local<Script> indexed_property_names_script = v8_compile(
5939  "keys = new Array(); keys[125000] = 1;"
5940  "for(i = 0; i < 80000; i++) { keys[i] = i; };"
5941  "keys.length = 25; keys;");
5942  Local<Value> result = indexed_property_names_script->Run();
5943  info.GetReturnValue().Set(Local<v8::Array>::Cast(result));
5944 }
5945 
5946 
5947 // Make sure that the the interceptor code in the runtime properly handles
5948 // merging property name lists for double-array-backed arrays.
5949 THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
5950  v8::Isolate* isolate = CcTest::isolate();
5951  v8::HandleScope scope(isolate);
5952  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5953  templ->SetIndexedPropertyHandler(UnboxedDoubleIndexedPropertyGetter,
5954  UnboxedDoubleIndexedPropertySetter,
5955  0,
5956  0,
5958  LocalContext context;
5959  context->Global()->Set(v8_str("obj"), templ->NewInstance());
5960  // When obj is created, force it to be Stored in a FastDoubleArray.
5961  Local<Script> create_unboxed_double_script = v8_compile(
5962  "obj[125000] = 1; for(i = 0; i < 80000; i+=2) { obj[i] = i; } "
5963  "key_count = 0; "
5964  "for (x in obj) {key_count++;};"
5965  "obj;");
5966  Local<Value> result = create_unboxed_double_script->Run();
5967  CHECK(result->ToObject()->HasRealIndexedProperty(2000));
5968  Local<Script> key_count_check = v8_compile("key_count;");
5969  result = key_count_check->Run();
5970  CHECK_EQ(v8_num(40013), result);
5971 }
5972 
5973 
5976  // Force the list of returned keys to be stored in a Arguments object.
5977  Local<Script> indexed_property_names_script = v8_compile(
5978  "function f(w,x) {"
5979  " return arguments;"
5980  "}"
5981  "keys = f(0, 1, 2, 3);"
5982  "keys;");
5983  Local<Object> result =
5984  Local<Object>::Cast(indexed_property_names_script->Run());
5985  // Have to populate the handle manually, as it's not Cast-able.
5987  v8::Utils::OpenHandle<Object, i::JSObject>(result);
5988  i::Handle<i::JSArray> array(reinterpret_cast<i::JSArray*>(*o));
5989  info.GetReturnValue().Set(v8::Utils::ToLocal(array));
5990 }
5991 
5992 
5993 static void SloppyIndexedPropertyGetter(
5994  uint32_t index,
5997  if (index < 4) {
5998  info.GetReturnValue().Set(v8_num(index));
5999  }
6000 }
6001 
6002 
6003 // Make sure that the the interceptor code in the runtime properly handles
6004 // merging property name lists for non-string arguments arrays.
6005 THREADED_TEST(IndexedInterceptorSloppyArgsWithIndexedAccessor) {
6006  v8::Isolate* isolate = CcTest::isolate();
6007  v8::HandleScope scope(isolate);
6008  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6009  templ->SetIndexedPropertyHandler(SloppyIndexedPropertyGetter,
6010  0,
6011  0,
6012  0,
6014  LocalContext context;
6015  context->Global()->Set(v8_str("obj"), templ->NewInstance());
6016  Local<Script> create_args_script = v8_compile(
6017  "var key_count = 0;"
6018  "for (x in obj) {key_count++;} key_count;");
6019  Local<Value> result = create_args_script->Run();
6020  CHECK_EQ(v8_num(4), result);
6021 }
6022 
6023 
6024 static void IdentityIndexedPropertyGetter(
6025  uint32_t index,
6027  info.GetReturnValue().Set(index);
6028 }
6029 
6030 
6031 THREADED_TEST(IndexedInterceptorWithGetOwnPropertyDescriptor) {
6032  v8::Isolate* isolate = CcTest::isolate();
6033  v8::HandleScope scope(isolate);
6034  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6035  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6036 
6037  LocalContext context;
6038  context->Global()->Set(v8_str("obj"), templ->NewInstance());
6039 
6040  // Check fast object case.
6041  const char* fast_case_code =
6042  "Object.getOwnPropertyDescriptor(obj, 0).value.toString()";
6043  ExpectString(fast_case_code, "0");
6044 
6045  // Check slow case.
6046  const char* slow_case_code =
6047  "obj.x = 1; delete obj.x;"
6048  "Object.getOwnPropertyDescriptor(obj, 1).value.toString()";
6049  ExpectString(slow_case_code, "1");
6050 }
6051 
6052 
6053 THREADED_TEST(IndexedInterceptorWithNoSetter) {
6054  v8::Isolate* isolate = CcTest::isolate();
6055  v8::HandleScope scope(isolate);
6056  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6057  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6058 
6059  LocalContext context;
6060  context->Global()->Set(v8_str("obj"), templ->NewInstance());
6061 
6062  const char* code =
6063  "try {"
6064  " obj[0] = 239;"
6065  " for (var i = 0; i < 100; i++) {"
6066  " var v = obj[0];"
6067  " if (v != 0) throw 'Wrong value ' + v + ' at iteration ' + i;"
6068  " }"
6069  " 'PASSED'"
6070  "} catch(e) {"
6071  " e"
6072  "}";
6073  ExpectString(code, "PASSED");
6074 }
6075 
6076 
6077 THREADED_TEST(IndexedInterceptorWithAccessorCheck) {
6078  v8::Isolate* isolate = CcTest::isolate();
6079  v8::HandleScope scope(isolate);
6080  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6081  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6082 
6083  LocalContext context;
6084  Local<v8::Object> obj = templ->NewInstance();
6085  obj->TurnOnAccessCheck();
6086  context->Global()->Set(v8_str("obj"), obj);
6087 
6088  const char* code =
6089  "try {"
6090  " for (var i = 0; i < 100; i++) {"
6091  " var v = obj[0];"
6092  " if (v != undefined) throw 'Wrong value ' + v + ' at iteration ' + i;"
6093  " }"
6094  " 'PASSED'"
6095  "} catch(e) {"
6096  " e"
6097  "}";
6098  ExpectString(code, "PASSED");
6099 }
6100 
6101 
6102 THREADED_TEST(IndexedInterceptorWithAccessorCheckSwitchedOn) {
6103  i::FLAG_allow_natives_syntax = true;
6104  v8::Isolate* isolate = CcTest::isolate();
6105  v8::HandleScope scope(isolate);
6106  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6107  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6108 
6109  LocalContext context;
6110  Local<v8::Object> obj = templ->NewInstance();
6111  context->Global()->Set(v8_str("obj"), obj);
6112 
6113  const char* code =
6114  "try {"
6115  " for (var i = 0; i < 100; i++) {"
6116  " var expected = i;"
6117  " if (i == 5) {"
6118  " %EnableAccessChecks(obj);"
6119  " expected = undefined;"
6120  " }"
6121  " var v = obj[i];"
6122  " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6123  " if (i == 5) %DisableAccessChecks(obj);"
6124  " }"
6125  " 'PASSED'"
6126  "} catch(e) {"
6127  " e"
6128  "}";
6129  ExpectString(code, "PASSED");
6130 }
6131 
6132 
6133 THREADED_TEST(IndexedInterceptorWithDifferentIndices) {
6134  v8::Isolate* isolate = CcTest::isolate();
6135  v8::HandleScope scope(isolate);
6136  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6137  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6138 
6139  LocalContext context;
6140  Local<v8::Object> obj = templ->NewInstance();
6141  context->Global()->Set(v8_str("obj"), obj);
6142 
6143  const char* code =
6144  "try {"
6145  " for (var i = 0; i < 100; i++) {"
6146  " var v = obj[i];"
6147  " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6148  " }"
6149  " 'PASSED'"
6150  "} catch(e) {"
6151  " e"
6152  "}";
6153  ExpectString(code, "PASSED");
6154 }
6155 
6156 
6157 THREADED_TEST(IndexedInterceptorWithNegativeIndices) {
6158  v8::Isolate* isolate = CcTest::isolate();
6159  v8::HandleScope scope(isolate);
6160  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6161  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6162 
6163  LocalContext context;
6164  Local<v8::Object> obj = templ->NewInstance();
6165  context->Global()->Set(v8_str("obj"), obj);
6166 
6167  const char* code =
6168  "try {"
6169  " for (var i = 0; i < 100; i++) {"
6170  " var expected = i;"
6171  " var key = i;"
6172  " if (i == 25) {"
6173  " key = -1;"
6174  " expected = undefined;"
6175  " }"
6176  " if (i == 50) {"
6177  " /* probe minimal Smi number on 32-bit platforms */"
6178  " key = -(1 << 30);"
6179  " expected = undefined;"
6180  " }"
6181  " if (i == 75) {"
6182  " /* probe minimal Smi number on 64-bit platforms */"
6183  " key = 1 << 31;"
6184  " expected = undefined;"
6185  " }"
6186  " var v = obj[key];"
6187  " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6188  " }"
6189  " 'PASSED'"
6190  "} catch(e) {"
6191  " e"
6192  "}";
6193  ExpectString(code, "PASSED");
6194 }
6195 
6196 
6197 THREADED_TEST(IndexedInterceptorWithNotSmiLookup) {
6198  v8::Isolate* isolate = CcTest::isolate();
6199  v8::HandleScope scope(isolate);
6200  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6201  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6202 
6203  LocalContext context;
6204  Local<v8::Object> obj = templ->NewInstance();
6205  context->Global()->Set(v8_str("obj"), obj);
6206 
6207  const char* code =
6208  "try {"
6209  " for (var i = 0; i < 100; i++) {"
6210  " var expected = i;"
6211  " var key = i;"
6212  " if (i == 50) {"
6213  " key = 'foobar';"
6214  " expected = undefined;"
6215  " }"
6216  " var v = obj[key];"
6217  " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6218  " }"
6219  " 'PASSED'"
6220  "} catch(e) {"
6221  " e"
6222  "}";
6223  ExpectString(code, "PASSED");
6224 }
6225 
6226 
6227 THREADED_TEST(IndexedInterceptorGoingMegamorphic) {
6228  v8::Isolate* isolate = CcTest::isolate();
6229  v8::HandleScope scope(isolate);
6230  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6231  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6232 
6233  LocalContext context;
6234  Local<v8::Object> obj = templ->NewInstance();
6235  context->Global()->Set(v8_str("obj"), obj);
6236 
6237  const char* code =
6238  "var original = obj;"
6239  "try {"
6240  " for (var i = 0; i < 100; i++) {"
6241  " var expected = i;"
6242  " if (i == 50) {"
6243  " obj = {50: 'foobar'};"
6244  " expected = 'foobar';"
6245  " }"
6246  " var v = obj[i];"
6247  " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6248  " if (i == 50) obj = original;"
6249  " }"
6250  " 'PASSED'"
6251  "} catch(e) {"
6252  " e"
6253  "}";
6254  ExpectString(code, "PASSED");
6255 }
6256 
6257 
6258 THREADED_TEST(IndexedInterceptorReceiverTurningSmi) {
6259  v8::Isolate* isolate = CcTest::isolate();
6260  v8::HandleScope scope(isolate);
6261  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6262  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6263 
6264  LocalContext context;
6265  Local<v8::Object> obj = templ->NewInstance();
6266  context->Global()->Set(v8_str("obj"), obj);
6267 
6268  const char* code =
6269  "var original = obj;"
6270  "try {"
6271  " for (var i = 0; i < 100; i++) {"
6272  " var expected = i;"
6273  " if (i == 5) {"
6274  " obj = 239;"
6275  " expected = undefined;"
6276  " }"
6277  " var v = obj[i];"
6278  " if (v != expected) throw 'Wrong value ' + v + ' at iteration ' + i;"
6279  " if (i == 5) obj = original;"
6280  " }"
6281  " 'PASSED'"
6282  "} catch(e) {"
6283  " e"
6284  "}";
6285  ExpectString(code, "PASSED");
6286 }
6287 
6288 
6289 THREADED_TEST(IndexedInterceptorOnProto) {
6290  v8::Isolate* isolate = CcTest::isolate();
6291  v8::HandleScope scope(isolate);
6292  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6293  templ->SetIndexedPropertyHandler(IdentityIndexedPropertyGetter);
6294 
6295  LocalContext context;
6296  Local<v8::Object> obj = templ->NewInstance();
6297  context->Global()->Set(v8_str("obj"), obj);
6298 
6299  const char* code =
6300  "var o = {__proto__: obj};"
6301  "try {"
6302  " for (var i = 0; i < 100; i++) {"
6303  " var v = o[i];"
6304  " if (v != i) throw 'Wrong value ' + v + ' at iteration ' + i;"
6305  " }"
6306  " 'PASSED'"
6307  "} catch(e) {"
6308  " e"
6309  "}";
6310  ExpectString(code, "PASSED");
6311 }
6312 
6313 
6314 THREADED_TEST(MultiContexts) {
6315  v8::Isolate* isolate = CcTest::isolate();
6316  v8::HandleScope scope(isolate);
6317  v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6318  templ->Set(v8_str("dummy"), v8::FunctionTemplate::New(isolate,
6319  DummyCallHandler));
6320 
6321  Local<String> password = v8_str("Password");
6322 
6323  // Create an environment
6324  LocalContext context0(0, templ);
6325  context0->SetSecurityToken(password);
6326  v8::Handle<v8::Object> global0 = context0->Global();
6327  global0->Set(v8_str("custom"), v8_num(1234));
6328  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6329 
6330  // Create an independent environment
6331  LocalContext context1(0, templ);
6332  context1->SetSecurityToken(password);
6333  v8::Handle<v8::Object> global1 = context1->Global();
6334  global1->Set(v8_str("custom"), v8_num(1234));
6335  CHECK_NE(global0, global1);
6336  CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
6337  CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
6338 
6339  // Now create a new context with the old global
6340  LocalContext context2(0, templ, global1);
6341  context2->SetSecurityToken(password);
6342  v8::Handle<v8::Object> global2 = context2->Global();
6343  CHECK_EQ(global1, global2);
6344  CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
6345  CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
6346 }
6347 
6348 
6349 THREADED_TEST(FunctionPrototypeAcrossContexts) {
6350  // Make sure that functions created by cloning boilerplates cannot
6351  // communicate through their __proto__ field.
6352 
6354 
6355  LocalContext env0;
6356  v8::Handle<v8::Object> global0 =
6357  env0->Global();
6358  v8::Handle<v8::Object> object0 =
6359  global0->Get(v8_str("Object")).As<v8::Object>();
6360  v8::Handle<v8::Object> tostring0 =
6361  object0->Get(v8_str("toString")).As<v8::Object>();
6362  v8::Handle<v8::Object> proto0 =
6363  tostring0->Get(v8_str("__proto__")).As<v8::Object>();
6364  proto0->Set(v8_str("custom"), v8_num(1234));
6365 
6366  LocalContext env1;
6367  v8::Handle<v8::Object> global1 =
6368  env1->Global();
6369  v8::Handle<v8::Object> object1 =
6370  global1->Get(v8_str("Object")).As<v8::Object>();
6371  v8::Handle<v8::Object> tostring1 =
6372  object1->Get(v8_str("toString")).As<v8::Object>();
6373  v8::Handle<v8::Object> proto1 =
6374  tostring1->Get(v8_str("__proto__")).As<v8::Object>();
6375  CHECK(!proto1->Has(v8_str("custom")));
6376 }
6377 
6378 
6379 THREADED_TEST(Regress892105) {
6380  // Make sure that object and array literals created by cloning
6381  // boilerplates cannot communicate through their __proto__
6382  // field. This is rather difficult to check, but we try to add stuff
6383  // to Object.prototype and Array.prototype and create a new
6384  // environment. This should succeed.
6385 
6387 
6388  Local<String> source = v8_str("Object.prototype.obj = 1234;"
6389  "Array.prototype.arr = 4567;"
6390  "8901");
6391 
6392  LocalContext env0;
6393  Local<Script> script0 = v8_compile(source);
6394  CHECK_EQ(8901.0, script0->Run()->NumberValue());
6395 
6396  LocalContext env1;
6397  Local<Script> script1 = v8_compile(source);
6398  CHECK_EQ(8901.0, script1->Run()->NumberValue());
6399 }
6400 
6401 
6402 THREADED_TEST(UndetectableObject) {
6403  LocalContext env;
6404  v8::HandleScope scope(env->GetIsolate());
6405 
6406  Local<v8::FunctionTemplate> desc =
6408  desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6409 
6410  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6411  env->Global()->Set(v8_str("undetectable"), obj);
6412 
6413  ExpectString("undetectable.toString()", "[object Object]");
6414  ExpectString("typeof undetectable", "undefined");
6415  ExpectString("typeof(undetectable)", "undefined");
6416  ExpectBoolean("typeof undetectable == 'undefined'", true);
6417  ExpectBoolean("typeof undetectable == 'object'", false);
6418  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6419  ExpectBoolean("!undetectable", true);
6420 
6421  ExpectObject("true&&undetectable", obj);
6422  ExpectBoolean("false&&undetectable", false);
6423  ExpectBoolean("true||undetectable", true);
6424  ExpectObject("false||undetectable", obj);
6425 
6426  ExpectObject("undetectable&&true", obj);
6427  ExpectObject("undetectable&&false", obj);
6428  ExpectBoolean("undetectable||true", true);
6429  ExpectBoolean("undetectable||false", false);
6430 
6431  ExpectBoolean("undetectable==null", true);
6432  ExpectBoolean("null==undetectable", true);
6433  ExpectBoolean("undetectable==undefined", true);
6434  ExpectBoolean("undefined==undetectable", true);
6435  ExpectBoolean("undetectable==undetectable", true);
6436 
6437 
6438  ExpectBoolean("undetectable===null", false);
6439  ExpectBoolean("null===undetectable", false);
6440  ExpectBoolean("undetectable===undefined", false);
6441  ExpectBoolean("undefined===undetectable", false);
6442  ExpectBoolean("undetectable===undetectable", true);
6443 }
6444 
6445 
6446 THREADED_TEST(VoidLiteral) {
6447  LocalContext env;
6448  v8::Isolate* isolate = env->GetIsolate();
6449  v8::HandleScope scope(isolate);
6450 
6451  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
6452  desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6453 
6454  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6455  env->Global()->Set(v8_str("undetectable"), obj);
6456 
6457  ExpectBoolean("undefined == void 0", true);
6458  ExpectBoolean("undetectable == void 0", true);
6459  ExpectBoolean("null == void 0", true);
6460  ExpectBoolean("undefined === void 0", true);
6461  ExpectBoolean("undetectable === void 0", false);
6462  ExpectBoolean("null === void 0", false);
6463 
6464  ExpectBoolean("void 0 == undefined", true);
6465  ExpectBoolean("void 0 == undetectable", true);
6466  ExpectBoolean("void 0 == null", true);
6467  ExpectBoolean("void 0 === undefined", true);
6468  ExpectBoolean("void 0 === undetectable", false);
6469  ExpectBoolean("void 0 === null", false);
6470 
6471  ExpectString("(function() {"
6472  " try {"
6473  " return x === void 0;"
6474  " } catch(e) {"
6475  " return e.toString();"
6476  " }"
6477  "})()",
6478  "ReferenceError: x is not defined");
6479  ExpectString("(function() {"
6480  " try {"
6481  " return void 0 === x;"
6482  " } catch(e) {"
6483  " return e.toString();"
6484  " }"
6485  "})()",
6486  "ReferenceError: x is not defined");
6487 }
6488 
6489 
6490 THREADED_TEST(ExtensibleOnUndetectable) {
6491  LocalContext env;
6492  v8::Isolate* isolate = env->GetIsolate();
6493  v8::HandleScope scope(isolate);
6494 
6495  Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
6496  desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
6497 
6498  Local<v8::Object> obj = desc->GetFunction()->NewInstance();
6499  env->Global()->Set(v8_str("undetectable"), obj);
6500 
6501  Local<String> source = v8_str("undetectable.x = 42;"
6502  "undetectable.x");
6503 
6504  Local<Script> script = v8_compile(source);
6505 
6506  CHECK_EQ(v8::Integer::New(isolate, 42), script->Run());
6507 
6508  ExpectBoolean("Object.isExtensible(undetectable)", true);
6509 
6510  source = v8_str("Object.preventExtensions(undetectable);");
6511  script = v8_compile(source);
6512  script->Run();
6513  ExpectBoolean("Object.isExtensible(undetectable)", false);
6514 
6515  source = v8_str("undetectable.y = 2000;");
6516  script = v8_compile(source);
6517  script->Run();
6518  ExpectBoolean("undetectable.y == undefined", true);
6519 }
6520 
6521 
6522 
6523 THREADED_TEST(UndetectableString) {
6524  LocalContext env;
6525  v8::HandleScope scope(env->GetIsolate());
6526 
6527  Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6528  String::kUndetectableString);
6529  env->Global()->Set(v8_str("undetectable"), obj);
6530 
6531  ExpectString("undetectable", "foo");
6532  ExpectString("typeof undetectable", "undefined");
6533  ExpectString("typeof(undetectable)", "undefined");
6534  ExpectBoolean("typeof undetectable == 'undefined'", true);
6535  ExpectBoolean("typeof undetectable == 'string'", false);
6536  ExpectBoolean("if (undetectable) { true; } else { false; }", false);
6537  ExpectBoolean("!undetectable", true);
6538 
6539  ExpectObject("true&&undetectable", obj);
6540  ExpectBoolean("false&&undetectable", false);
6541  ExpectBoolean("true||undetectable", true);
6542  ExpectObject("false||undetectable", obj);
6543 
6544  ExpectObject("undetectable&&true", obj);
6545  ExpectObject("undetectable&&false", obj);
6546  ExpectBoolean("undetectable||true", true);
6547  ExpectBoolean("undetectable||false", false);
6548 
6549  ExpectBoolean("undetectable==null", true);
6550  ExpectBoolean("null==undetectable", true);
6551  ExpectBoolean("undetectable==undefined", true);
6552  ExpectBoolean("undefined==undetectable", true);
6553  ExpectBoolean("undetectable==undetectable", true);
6554 
6555 
6556  ExpectBoolean("undetectable===null", false);
6557  ExpectBoolean("null===undetectable", false);
6558  ExpectBoolean("undetectable===undefined", false);
6559  ExpectBoolean("undefined===undetectable", false);
6560  ExpectBoolean("undetectable===undetectable", true);
6561 }
6562 
6563 
6564 TEST(UndetectableOptimized) {
6565  i::FLAG_allow_natives_syntax = true;
6566  LocalContext env;
6567  v8::HandleScope scope(env->GetIsolate());
6568 
6569  Local<String> obj = String::NewFromUtf8(env->GetIsolate(), "foo",
6570  String::kUndetectableString);
6571  env->Global()->Set(v8_str("undetectable"), obj);
6572  env->Global()->Set(v8_str("detectable"), v8_str("bar"));
6573 
6574  ExpectString(
6575  "function testBranch() {"
6576  " if (!%_IsUndetectableObject(undetectable)) throw 1;"
6577  " if (%_IsUndetectableObject(detectable)) throw 2;"
6578  "}\n"
6579  "function testBool() {"
6580  " var b1 = !%_IsUndetectableObject(undetectable);"
6581  " var b2 = %_IsUndetectableObject(detectable);"
6582  " if (b1) throw 3;"
6583  " if (b2) throw 4;"
6584  " return b1 == b2;"
6585  "}\n"
6586  "%OptimizeFunctionOnNextCall(testBranch);"
6587  "%OptimizeFunctionOnNextCall(testBool);"
6588  "for (var i = 0; i < 10; i++) {"
6589  " testBranch();"
6590  " testBool();"
6591  "}\n"
6592  "\"PASS\"",
6593  "PASS");
6594 }
6595 
6596 
6597 template <typename T> static void USE(T) { }
6598 
6599 
6600 // The point of this test is type checking. We run it only so compilers
6601 // don't complain about an unused function.
6602 TEST(PersistentHandles) {
6603  LocalContext env;
6604  v8::Isolate* isolate = CcTest::isolate();
6605  v8::HandleScope scope(isolate);
6606  Local<String> str = v8_str("foo");
6607  v8::Persistent<String> p_str(isolate, str);
6608  p_str.Reset();
6609  Local<Script> scr = v8_compile("");
6610  v8::Persistent<Script> p_scr(isolate, scr);
6611  p_scr.Reset();
6612  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6613  v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6614  p_templ.Reset();
6615 }
6616 
6617 
6618 static void HandleLogDelegator(
6621 }
6622 
6623 
6624 THREADED_TEST(GlobalObjectTemplate) {
6625  v8::Isolate* isolate = CcTest::isolate();
6626  v8::HandleScope handle_scope(isolate);
6627  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
6628  global_template->Set(v8_str("JSNI_Log"),
6629  v8::FunctionTemplate::New(isolate, HandleLogDelegator));
6630  v8::Local<Context> context = Context::New(isolate, 0, global_template);
6631  Context::Scope context_scope(context);
6632  CompileRun("JSNI_Log('LOG')");
6633 }
6634 
6635 
6636 static const char* kSimpleExtensionSource =
6637  "function Foo() {"
6638  " return 4;"
6639  "}";
6640 
6641 
6642 TEST(SimpleExtensions) {
6643  v8::HandleScope handle_scope(CcTest::isolate());
6644  v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6645  const char* extension_names[] = { "simpletest" };
6646  v8::ExtensionConfiguration extensions(1, extension_names);
6647  v8::Handle<Context> context =
6648  Context::New(CcTest::isolate(), &extensions);
6649  Context::Scope lock(context);
6650  v8::Handle<Value> result = CompileRun("Foo()");
6651  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
6652 }
6653 
6654 
6655 TEST(NullExtensions) {
6656  v8::HandleScope handle_scope(CcTest::isolate());
6657  v8::RegisterExtension(new Extension("nulltest", NULL));
6658  const char* extension_names[] = { "nulltest" };
6659  v8::ExtensionConfiguration extensions(1, extension_names);
6660  v8::Handle<Context> context =
6661  Context::New(CcTest::isolate(), &extensions);
6662  Context::Scope lock(context);
6663  v8::Handle<Value> result = CompileRun("1+3");
6664  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
6665 }
6666 
6667 
6668 static const char* kEmbeddedExtensionSource =
6669  "function Ret54321(){return 54321;}~~@@$"
6670  "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6671 static const int kEmbeddedExtensionSourceValidLen = 34;
6672 
6673 
6674 TEST(ExtensionMissingSourceLength) {
6675  v8::HandleScope handle_scope(CcTest::isolate());
6676  v8::RegisterExtension(new Extension("srclentest_fail",
6677  kEmbeddedExtensionSource));
6678  const char* extension_names[] = { "srclentest_fail" };
6679  v8::ExtensionConfiguration extensions(1, extension_names);
6680  v8::Handle<Context> context =
6681  Context::New(CcTest::isolate(), &extensions);
6682  CHECK_EQ(0, *context);
6683 }
6684 
6685 
6686 TEST(ExtensionWithSourceLength) {
6687  for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6688  source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
6689  v8::HandleScope handle_scope(CcTest::isolate());
6690  i::ScopedVector<char> extension_name(32);
6691  i::OS::SNPrintF(extension_name, "ext #%d", source_len);
6692  v8::RegisterExtension(new Extension(extension_name.start(),
6693  kEmbeddedExtensionSource, 0, 0,
6694  source_len));
6695  const char* extension_names[1] = { extension_name.start() };
6696  v8::ExtensionConfiguration extensions(1, extension_names);
6697  v8::Handle<Context> context =
6698  Context::New(CcTest::isolate(), &extensions);
6699  if (source_len == kEmbeddedExtensionSourceValidLen) {
6700  Context::Scope lock(context);
6701  v8::Handle<Value> result = CompileRun("Ret54321()");
6702  CHECK_EQ(v8::Integer::New(CcTest::isolate(), 54321), result);
6703  } else {
6704  // Anything but exactly the right length should fail to compile.
6705  CHECK_EQ(0, *context);
6706  }
6707  }
6708 }
6709 
6710 
6711 static const char* kEvalExtensionSource1 =
6712  "function UseEval1() {"
6713  " var x = 42;"
6714  " return eval('x');"
6715  "}";
6716 
6717 
6718 static const char* kEvalExtensionSource2 =
6719  "(function() {"
6720  " var x = 42;"
6721  " function e() {"
6722  " return eval('x');"
6723  " }"
6724  " this.UseEval2 = e;"
6725  "})()";
6726 
6727 
6728 TEST(UseEvalFromExtension) {
6729  v8::HandleScope handle_scope(CcTest::isolate());
6730  v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6731  v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6732  const char* extension_names[] = { "evaltest1", "evaltest2" };
6733  v8::ExtensionConfiguration extensions(2, extension_names);
6734  v8::Handle<Context> context =
6735  Context::New(CcTest::isolate(), &extensions);
6736  Context::Scope lock(context);
6737  v8::Handle<Value> result = CompileRun("UseEval1()");
6738  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
6739  result = CompileRun("UseEval2()");
6740  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
6741 }
6742 
6743 
6744 static const char* kWithExtensionSource1 =
6745  "function UseWith1() {"
6746  " var x = 42;"
6747  " with({x:87}) { return x; }"
6748  "}";
6749 
6750 
6751 
6752 static const char* kWithExtensionSource2 =
6753  "(function() {"
6754  " var x = 42;"
6755  " function e() {"
6756  " with ({x:87}) { return x; }"
6757  " }"
6758  " this.UseWith2 = e;"
6759  "})()";
6760 
6761 
6762 TEST(UseWithFromExtension) {
6763  v8::HandleScope handle_scope(CcTest::isolate());
6764  v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6765  v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6766  const char* extension_names[] = { "withtest1", "withtest2" };
6767  v8::ExtensionConfiguration extensions(2, extension_names);
6768  v8::Handle<Context> context =
6769  Context::New(CcTest::isolate(), &extensions);
6770  Context::Scope lock(context);
6771  v8::Handle<Value> result = CompileRun("UseWith1()");
6772  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
6773  result = CompileRun("UseWith2()");
6774  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 87));
6775 }
6776 
6777 
6778 TEST(AutoExtensions) {
6779  v8::HandleScope handle_scope(CcTest::isolate());
6780  Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6781  extension->set_auto_enable(true);
6782  v8::RegisterExtension(extension);
6783  v8::Handle<Context> context =
6784  Context::New(CcTest::isolate());
6785  Context::Scope lock(context);
6786  v8::Handle<Value> result = CompileRun("Foo()");
6787  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 4));
6788 }
6789 
6790 
6791 static const char* kSyntaxErrorInExtensionSource =
6792  "[";
6793 
6794 
6795 // Test that a syntax error in an extension does not cause a fatal
6796 // error but results in an empty context.
6797 TEST(SyntaxErrorExtensions) {
6798  v8::HandleScope handle_scope(CcTest::isolate());
6799  v8::RegisterExtension(new Extension("syntaxerror",
6800  kSyntaxErrorInExtensionSource));
6801  const char* extension_names[] = { "syntaxerror" };
6802  v8::ExtensionConfiguration extensions(1, extension_names);
6803  v8::Handle<Context> context =
6804  Context::New(CcTest::isolate(), &extensions);
6805  CHECK(context.IsEmpty());
6806 }
6807 
6808 
6809 static const char* kExceptionInExtensionSource =
6810  "throw 42";
6811 
6812 
6813 // Test that an exception when installing an extension does not cause
6814 // a fatal error but results in an empty context.
6815 TEST(ExceptionExtensions) {
6816  v8::HandleScope handle_scope(CcTest::isolate());
6817  v8::RegisterExtension(new Extension("exception",
6818  kExceptionInExtensionSource));
6819  const char* extension_names[] = { "exception" };
6820  v8::ExtensionConfiguration extensions(1, extension_names);
6821  v8::Handle<Context> context =
6822  Context::New(CcTest::isolate(), &extensions);
6823  CHECK(context.IsEmpty());
6824 }
6825 
6826 
6827 static const char* kNativeCallInExtensionSource =
6828  "function call_runtime_last_index_of(x) {"
6829  " return %StringLastIndexOf(x, 'bob', 10);"
6830  "}";
6831 
6832 
6833 static const char* kNativeCallTest =
6834  "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6835 
6836 // Test that a native runtime calls are supported in extensions.
6837 TEST(NativeCallInExtensions) {
6838  v8::HandleScope handle_scope(CcTest::isolate());
6839  v8::RegisterExtension(new Extension("nativecall",
6840  kNativeCallInExtensionSource));
6841  const char* extension_names[] = { "nativecall" };
6842  v8::ExtensionConfiguration extensions(1, extension_names);
6843  v8::Handle<Context> context =
6844  Context::New(CcTest::isolate(), &extensions);
6845  Context::Scope lock(context);
6846  v8::Handle<Value> result = CompileRun(kNativeCallTest);
6847  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 3));
6848 }
6849 
6850 
6851 class NativeFunctionExtension : public Extension {
6852  public:
6853  NativeFunctionExtension(const char* name,
6854  const char* source,
6855  v8::FunctionCallback fun = &Echo)
6856  : Extension(name, source),
6857  function_(fun) { }
6858 
6860  v8::Isolate* isolate,
6861  v8::Handle<v8::String> name) {
6862  return v8::FunctionTemplate::New(isolate, function_);
6863  }
6864 
6865  static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6866  if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
6867  }
6868  private:
6869  v8::FunctionCallback function_;
6870 };
6871 
6872 
6873 TEST(NativeFunctionDeclaration) {
6874  v8::HandleScope handle_scope(CcTest::isolate());
6875  const char* name = "nativedecl";
6877  "native function foo();"));
6878  const char* extension_names[] = { name };
6879  v8::ExtensionConfiguration extensions(1, extension_names);
6880  v8::Handle<Context> context =
6881  Context::New(CcTest::isolate(), &extensions);
6882  Context::Scope lock(context);
6883  v8::Handle<Value> result = CompileRun("foo(42);");
6884  CHECK_EQ(result, v8::Integer::New(CcTest::isolate(), 42));
6885 }
6886 
6887 
6888 TEST(NativeFunctionDeclarationError) {
6889  v8::HandleScope handle_scope(CcTest::isolate());
6890  const char* name = "nativedeclerr";
6891  // Syntax error in extension code.
6893  "native\nfunction foo();"));
6894  const char* extension_names[] = { name };
6895  v8::ExtensionConfiguration extensions(1, extension_names);
6896  v8::Handle<Context> context =
6897  Context::New(CcTest::isolate(), &extensions);
6898  CHECK(context.IsEmpty());
6899 }
6900 
6901 
6902 TEST(NativeFunctionDeclarationErrorEscape) {
6903  v8::HandleScope handle_scope(CcTest::isolate());
6904  const char* name = "nativedeclerresc";
6905  // Syntax error in extension code - escape code in "native" means that
6906  // it's not treated as a keyword.
6908  name,
6909  "nativ\\u0065 function foo();"));
6910  const char* extension_names[] = { name };
6911  v8::ExtensionConfiguration extensions(1, extension_names);
6912  v8::Handle<Context> context =
6913  Context::New(CcTest::isolate(), &extensions);
6914  CHECK(context.IsEmpty());
6915 }
6916 
6917 
6918 static void CheckDependencies(const char* name, const char* expected) {
6919  v8::HandleScope handle_scope(CcTest::isolate());
6920  v8::ExtensionConfiguration config(1, &name);
6921  LocalContext context(&config);
6922  CHECK_EQ(String::NewFromUtf8(CcTest::isolate(), expected),
6923  context->Global()->Get(v8_str("loaded")));
6924 }
6925 
6926 
6927 /*
6928  * Configuration:
6929  *
6930  * /-- B <--\
6931  * A <- -- D <-- E
6932  * \-- C <--/
6933  */
6934 THREADED_TEST(ExtensionDependency) {
6935  static const char* kEDeps[] = { "D" };
6936  v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6937  static const char* kDDeps[] = { "B", "C" };
6938  v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6939  static const char* kBCDeps[] = { "A" };
6940  v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6941  v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6942  v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6943  CheckDependencies("A", "undefinedA");
6944  CheckDependencies("B", "undefinedAB");
6945  CheckDependencies("C", "undefinedAC");
6946  CheckDependencies("D", "undefinedABCD");
6947  CheckDependencies("E", "undefinedABCDE");
6948  v8::HandleScope handle_scope(CcTest::isolate());
6949  static const char* exts[2] = { "C", "E" };
6950  v8::ExtensionConfiguration config(2, exts);
6951  LocalContext context(&config);
6952  CHECK_EQ(v8_str("undefinedACBDE"), context->Global()->Get(v8_str("loaded")));
6953 }
6954 
6955 
6956 static const char* kExtensionTestScript =
6957  "native function A();"
6958  "native function B();"
6959  "native function C();"
6960  "function Foo(i) {"
6961  " if (i == 0) return A();"
6962  " if (i == 1) return B();"
6963  " if (i == 2) return C();"
6964  "}";
6965 
6966 
6967 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
6969  if (args.IsConstructCall()) {
6970  args.This()->Set(v8_str("data"), args.Data());
6971  args.GetReturnValue().SetNull();
6972  return;
6973  }
6974  args.GetReturnValue().Set(args.Data());
6975 }
6976 
6977 
6978 class FunctionExtension : public Extension {
6979  public:
6980  FunctionExtension() : Extension("functiontest", kExtensionTestScript) { }
6982  v8::Isolate* isolate,
6983  v8::Handle<String> name);
6984 };
6985 
6986 
6987 static int lookup_count = 0;
6989  v8::Isolate* isolate, v8::Handle<String> name) {
6990  lookup_count++;
6991  if (name->Equals(v8_str("A"))) {
6993  isolate, CallFun, v8::Integer::New(isolate, 8));
6994  } else if (name->Equals(v8_str("B"))) {
6996  isolate, CallFun, v8::Integer::New(isolate, 7));
6997  } else if (name->Equals(v8_str("C"))) {
6999  isolate, CallFun, v8::Integer::New(isolate, 6));
7000  } else {
7002  }
7003 }
7004 
7005 
7006 THREADED_TEST(FunctionLookup) {
7008  v8::HandleScope handle_scope(CcTest::isolate());
7009  static const char* exts[1] = { "functiontest" };
7010  v8::ExtensionConfiguration config(1, exts);
7011  LocalContext context(&config);
7012  CHECK_EQ(3, lookup_count);
7014  CompileRun("Foo(0)"));
7016  CompileRun("Foo(1)"));
7018  CompileRun("Foo(2)"));
7019 }
7020 
7021 
7022 THREADED_TEST(NativeFunctionConstructCall) {
7024  v8::HandleScope handle_scope(CcTest::isolate());
7025  static const char* exts[1] = { "functiontest" };
7026  v8::ExtensionConfiguration config(1, exts);
7027  LocalContext context(&config);
7028  for (int i = 0; i < 10; i++) {
7029  // Run a few times to ensure that allocation of objects doesn't
7030  // change behavior of a constructor function.
7032  CompileRun("(new A()).data"));
7034  CompileRun("(new B()).data"));
7036  CompileRun("(new C()).data"));
7037  }
7038 }
7039 
7040 
7041 static const char* last_location;
7042 static const char* last_message;
7043 void StoringErrorCallback(const char* location, const char* message) {
7044  if (last_location == NULL) {
7045  last_location = location;
7046  last_message = message;
7047  }
7048 }
7049 
7050 
7051 // ErrorReporting creates a circular extensions configuration and
7052 // tests that the fatal error handler gets called. This renders V8
7053 // unusable and therefore this test cannot be run in parallel.
7054 TEST(ErrorReporting) {
7056  static const char* aDeps[] = { "B" };
7057  v8::RegisterExtension(new Extension("A", "", 1, aDeps));
7058  static const char* bDeps[] = { "A" };
7059  v8::RegisterExtension(new Extension("B", "", 1, bDeps));
7060  last_location = NULL;
7061  v8::ExtensionConfiguration config(1, bDeps);
7062  v8::Handle<Context> context =
7063  Context::New(CcTest::isolate(), &config);
7064  CHECK(context.IsEmpty());
7065  CHECK_NE(last_location, NULL);
7066 }
7067 
7068 
7069 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
7070  v8::Handle<Value> data) {
7071  CHECK(message->GetScriptResourceName()->IsUndefined());
7073  message->GetLineNumber();
7074  message->GetSourceLine();
7075 }
7076 
7077 
7078 THREADED_TEST(ErrorWithMissingScriptInfo) {
7079  LocalContext context;
7080  v8::HandleScope scope(context->GetIsolate());
7081  v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
7082  CompileRun("throw Error()");
7083  v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
7084 }
7085 
7086 
7088  bool flag;
7090 };
7091 
7092 
7093 static void DisposeAndSetFlag(
7095  data.GetParameter()->handle.Reset();
7096  data.GetParameter()->flag = true;
7097 }
7098 
7099 
7100 THREADED_TEST(IndependentWeakHandle) {
7101  v8::Isolate* iso = CcTest::isolate();
7102  v8::HandleScope scope(iso);
7103  v8::Handle<Context> context = Context::New(iso);
7104  Context::Scope context_scope(context);
7105 
7106  FlagAndPersistent object_a, object_b;
7107 
7108  {
7109  v8::HandleScope handle_scope(iso);
7110  object_a.handle.Reset(iso, v8::Object::New(iso));
7111  object_b.handle.Reset(iso, v8::Object::New(iso));
7112  }
7113 
7114  object_a.flag = false;
7115  object_b.flag = false;
7116  object_a.handle.SetWeak(&object_a, &DisposeAndSetFlag);
7117  object_b.handle.SetWeak(&object_b, &DisposeAndSetFlag);
7118  CHECK(!object_b.handle.IsIndependent());
7119  object_a.handle.MarkIndependent();
7120  object_b.handle.MarkIndependent();
7121  CHECK(object_b.handle.IsIndependent());
7123  CHECK(object_a.flag);
7124  CHECK(object_b.flag);
7125 }
7126 
7127 
7128 static void InvokeScavenge() {
7130 }
7131 
7132 
7133 static void InvokeMarkSweep() {
7135 }
7136 
7137 
7138 static void ForceScavenge(
7140  data.GetParameter()->handle.Reset();
7141  data.GetParameter()->flag = true;
7142  InvokeScavenge();
7143 }
7144 
7145 
7146 static void ForceMarkSweep(
7148  data.GetParameter()->handle.Reset();
7149  data.GetParameter()->flag = true;
7150  InvokeMarkSweep();
7151 }
7152 
7153 
7154 THREADED_TEST(GCFromWeakCallbacks) {
7155  v8::Isolate* isolate = CcTest::isolate();
7156  v8::HandleScope scope(isolate);
7157  v8::Handle<Context> context = Context::New(isolate);
7158  Context::Scope context_scope(context);
7159 
7160  static const int kNumberOfGCTypes = 2;
7162  Callback;
7163  Callback gc_forcing_callback[kNumberOfGCTypes] =
7164  {&ForceScavenge, &ForceMarkSweep};
7165 
7166  typedef void (*GCInvoker)();
7167  GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
7168 
7169  for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
7170  for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
7171  FlagAndPersistent object;
7172  {
7173  v8::HandleScope handle_scope(isolate);
7174  object.handle.Reset(isolate, v8::Object::New(isolate));
7175  }
7176  object.flag = false;
7177  object.handle.SetWeak(&object, gc_forcing_callback[inner_gc]);
7178  object.handle.MarkIndependent();
7179  invoke_gc[outer_gc]();
7180  CHECK(object.flag);
7181  }
7182  }
7183 }
7184 
7185 
7186 static void RevivingCallback(
7188  data.GetParameter()->handle.ClearWeak();
7189  data.GetParameter()->flag = true;
7190 }
7191 
7192 
7193 THREADED_TEST(IndependentHandleRevival) {
7194  v8::Isolate* isolate = CcTest::isolate();
7195  v8::HandleScope scope(isolate);
7196  v8::Handle<Context> context = Context::New(isolate);
7197  Context::Scope context_scope(context);
7198 
7199  FlagAndPersistent object;
7200  {
7201  v8::HandleScope handle_scope(isolate);
7203  object.handle.Reset(isolate, o);
7204  o->Set(v8_str("x"), v8::Integer::New(isolate, 1));
7205  v8::Local<String> y_str = v8_str("y");
7206  o->Set(y_str, y_str);
7207  }
7208  object.flag = false;
7209  object.handle.SetWeak(&object, &RevivingCallback);
7210  object.handle.MarkIndependent();
7212  CHECK(object.flag);
7214  {
7215  v8::HandleScope handle_scope(isolate);
7217  v8::Local<v8::Object>::New(isolate, object.handle);
7218  v8::Local<String> y_str = v8_str("y");
7219  CHECK_EQ(v8::Integer::New(isolate, 1), o->Get(v8_str("x")));
7220  CHECK(o->Get(y_str)->Equals(y_str));
7221  }
7222 }
7223 
7224 
7226 
7227 
7228 static void ArgumentsTestCallback(
7231  v8::Isolate* isolate = args.GetIsolate();
7232  CHECK_EQ(args_fun, args.Callee());
7233  CHECK_EQ(3, args.Length());
7234  CHECK_EQ(v8::Integer::New(isolate, 1), args[0]);
7235  CHECK_EQ(v8::Integer::New(isolate, 2), args[1]);
7236  CHECK_EQ(v8::Integer::New(isolate, 3), args[2]);
7237  CHECK_EQ(v8::Undefined(isolate), args[3]);
7238  v8::HandleScope scope(args.GetIsolate());
7240 }
7241 
7242 
7243 THREADED_TEST(Arguments) {
7244  v8::Isolate* isolate = CcTest::isolate();
7245  v8::HandleScope scope(isolate);
7246  v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
7247  global->Set(v8_str("f"),
7248  v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
7249  LocalContext context(NULL, global);
7250  args_fun = context->Global()->Get(v8_str("f")).As<Function>();
7251  v8_compile("f(1, 2, 3)")->Run();
7252 }
7253 
7254 
7255 static void NoBlockGetterX(Local<String> name,
7257 }
7258 
7259 
7260 static void NoBlockGetterI(uint32_t index,
7262 }
7263 
7264 
7265 static void PDeleter(Local<String> name,
7267  if (!name->Equals(v8_str("foo"))) {
7268  return; // not intercepted
7269  }
7270 
7271  info.GetReturnValue().Set(false); // intercepted, don't delete the property
7272 }
7273 
7274 
7275 static void IDeleter(uint32_t index,
7277  if (index != 2) {
7278  return; // not intercepted
7279  }
7280 
7281  info.GetReturnValue().Set(false); // intercepted, don't delete the property
7282 }
7283 
7284 
7285 THREADED_TEST(Deleter) {
7286  v8::Isolate* isolate = CcTest::isolate();
7287  v8::HandleScope scope(isolate);
7288  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7289  obj->SetNamedPropertyHandler(NoBlockGetterX, NULL, NULL, PDeleter, NULL);
7290  obj->SetIndexedPropertyHandler(NoBlockGetterI, NULL, NULL, IDeleter, NULL);
7291  LocalContext context;
7292  context->Global()->Set(v8_str("k"), obj->NewInstance());
7293  CompileRun(
7294  "k.foo = 'foo';"
7295  "k.bar = 'bar';"
7296  "k[2] = 2;"
7297  "k[4] = 4;");
7298  CHECK(v8_compile("delete k.foo")->Run()->IsFalse());
7299  CHECK(v8_compile("delete k.bar")->Run()->IsTrue());
7300 
7301  CHECK_EQ(v8_compile("k.foo")->Run(), v8_str("foo"));
7302  CHECK(v8_compile("k.bar")->Run()->IsUndefined());
7303 
7304  CHECK(v8_compile("delete k[2]")->Run()->IsFalse());
7305  CHECK(v8_compile("delete k[4]")->Run()->IsTrue());
7306 
7307  CHECK_EQ(v8_compile("k[2]")->Run(), v8_num(2));
7308  CHECK(v8_compile("k[4]")->Run()->IsUndefined());
7309 }
7310 
7311 
7312 static void GetK(Local<String> name,
7315  if (name->Equals(v8_str("foo")) ||
7316  name->Equals(v8_str("bar")) ||
7317  name->Equals(v8_str("baz"))) {
7318  info.GetReturnValue().SetUndefined();
7319  }
7320 }
7321 
7322 
7323 static void IndexedGetK(uint32_t index,
7326  if (index == 0 || index == 1) info.GetReturnValue().SetUndefined();
7327 }
7328 
7329 
7330 static void NamedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
7332  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 3);
7333  result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("foo"));
7334  result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("bar"));
7335  result->Set(v8::Integer::New(info.GetIsolate(), 2), v8_str("baz"));
7336  info.GetReturnValue().Set(result);
7337 }
7338 
7339 
7340 static void IndexedEnum(const v8::PropertyCallbackInfo<v8::Array>& info) {
7342  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
7343  result->Set(v8::Integer::New(info.GetIsolate(), 0), v8_str("0"));
7344  result->Set(v8::Integer::New(info.GetIsolate(), 1), v8_str("1"));
7345  info.GetReturnValue().Set(result);
7346 }
7347 
7348 
7349 THREADED_TEST(Enumerators) {
7350  v8::Isolate* isolate = CcTest::isolate();
7351  v8::HandleScope scope(isolate);
7352  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7353  obj->SetNamedPropertyHandler(GetK, NULL, NULL, NULL, NamedEnum);
7354  obj->SetIndexedPropertyHandler(IndexedGetK, NULL, NULL, NULL, IndexedEnum);
7355  LocalContext context;
7356  context->Global()->Set(v8_str("k"), obj->NewInstance());
7358  "k[10] = 0;"
7359  "k.a = 0;"
7360  "k[5] = 0;"
7361  "k.b = 0;"
7362  "k[4294967295] = 0;"
7363  "k.c = 0;"
7364  "k[4294967296] = 0;"
7365  "k.d = 0;"
7366  "k[140000] = 0;"
7367  "k.e = 0;"
7368  "k[30000000000] = 0;"
7369  "k.f = 0;"
7370  "var result = [];"
7371  "for (var prop in k) {"
7372  " result.push(prop);"
7373  "}"
7374  "result"));
7375  // Check that we get all the property names returned including the
7376  // ones from the enumerators in the right order: indexed properties
7377  // in numerical order, indexed interceptor properties, named
7378  // properties in insertion order, named interceptor properties.
7379  // This order is not mandated by the spec, so this test is just
7380  // documenting our behavior.
7381  CHECK_EQ(17, result->Length());
7382  // Indexed properties in numerical order.
7383  CHECK_EQ(v8_str("5"), result->Get(v8::Integer::New(isolate, 0)));
7384  CHECK_EQ(v8_str("10"), result->Get(v8::Integer::New(isolate, 1)));
7385  CHECK_EQ(v8_str("140000"), result->Get(v8::Integer::New(isolate, 2)));
7386  CHECK_EQ(v8_str("4294967295"), result->Get(v8::Integer::New(isolate, 3)));
7387  // Indexed interceptor properties in the order they are returned
7388  // from the enumerator interceptor.
7389  CHECK_EQ(v8_str("0"), result->Get(v8::Integer::New(isolate, 4)));
7390  CHECK_EQ(v8_str("1"), result->Get(v8::Integer::New(isolate, 5)));
7391  // Named properties in insertion order.
7392  CHECK_EQ(v8_str("a"), result->Get(v8::Integer::New(isolate, 6)));
7393  CHECK_EQ(v8_str("b"), result->Get(v8::Integer::New(isolate, 7)));
7394  CHECK_EQ(v8_str("c"), result->Get(v8::Integer::New(isolate, 8)));
7395  CHECK_EQ(v8_str("4294967296"), result->Get(v8::Integer::New(isolate, 9)));
7396  CHECK_EQ(v8_str("d"), result->Get(v8::Integer::New(isolate, 10)));
7397  CHECK_EQ(v8_str("e"), result->Get(v8::Integer::New(isolate, 11)));
7398  CHECK_EQ(v8_str("30000000000"), result->Get(v8::Integer::New(isolate, 12)));
7399  CHECK_EQ(v8_str("f"), result->Get(v8::Integer::New(isolate, 13)));
7400  // Named interceptor properties.
7401  CHECK_EQ(v8_str("foo"), result->Get(v8::Integer::New(isolate, 14)));
7402  CHECK_EQ(v8_str("bar"), result->Get(v8::Integer::New(isolate, 15)));
7403  CHECK_EQ(v8_str("baz"), result->Get(v8::Integer::New(isolate, 16)));
7404 }
7405 
7406 
7409 
7410 
7411 static void PGetter(Local<String> name,
7414  p_getter_count++;
7415  v8::Handle<v8::Object> global =
7416  info.GetIsolate()->GetCurrentContext()->Global();
7417  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7418  if (name->Equals(v8_str("p1"))) {
7419  CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7420  } else if (name->Equals(v8_str("p2"))) {
7421  CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7422  } else if (name->Equals(v8_str("p3"))) {
7423  CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7424  } else if (name->Equals(v8_str("p4"))) {
7425  CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7426  }
7427 }
7428 
7429 
7430 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
7432  LocalContext context;
7433  context->Global()->Set(v8_str("o1"), obj->NewInstance());
7434  CompileRun(
7435  "o1.__proto__ = { };"
7436  "var o2 = { __proto__: o1 };"
7437  "var o3 = { __proto__: o2 };"
7438  "var o4 = { __proto__: o3 };"
7439  "for (var i = 0; i < 10; i++) o4.p4;"
7440  "for (var i = 0; i < 10; i++) o3.p3;"
7441  "for (var i = 0; i < 10; i++) o2.p2;"
7442  "for (var i = 0; i < 10; i++) o1.p1;");
7443 }
7444 
7445 
7446 static void PGetter2(Local<String> name,
7449  p_getter_count2++;
7450  v8::Handle<v8::Object> global =
7451  info.GetIsolate()->GetCurrentContext()->Global();
7452  CHECK_EQ(info.Holder(), global->Get(v8_str("o1")));
7453  if (name->Equals(v8_str("p1"))) {
7454  CHECK_EQ(info.This(), global->Get(v8_str("o1")));
7455  } else if (name->Equals(v8_str("p2"))) {
7456  CHECK_EQ(info.This(), global->Get(v8_str("o2")));
7457  } else if (name->Equals(v8_str("p3"))) {
7458  CHECK_EQ(info.This(), global->Get(v8_str("o3")));
7459  } else if (name->Equals(v8_str("p4"))) {
7460  CHECK_EQ(info.This(), global->Get(v8_str("o4")));
7461  }
7462 }
7463 
7464 
7465 THREADED_TEST(GetterHolders) {
7466  v8::Isolate* isolate = CcTest::isolate();
7467  v8::HandleScope scope(isolate);
7468  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7469  obj->SetAccessor(v8_str("p1"), PGetter);
7470  obj->SetAccessor(v8_str("p2"), PGetter);
7471  obj->SetAccessor(v8_str("p3"), PGetter);
7472  obj->SetAccessor(v8_str("p4"), PGetter);
7473  p_getter_count = 0;
7474  RunHolderTest(obj);
7475  CHECK_EQ(40, p_getter_count);
7476 }
7477 
7478 
7479 THREADED_TEST(PreInterceptorHolders) {
7480  v8::Isolate* isolate = CcTest::isolate();
7481  v8::HandleScope scope(isolate);
7482  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7483  obj->SetNamedPropertyHandler(PGetter2);
7484  p_getter_count2 = 0;
7485  RunHolderTest(obj);
7486  CHECK_EQ(40, p_getter_count2);
7487 }
7488 
7489 
7490 THREADED_TEST(ObjectInstantiation) {
7491  v8::Isolate* isolate = CcTest::isolate();
7492  v8::HandleScope scope(isolate);
7493  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
7494  templ->SetAccessor(v8_str("t"), PGetter2);
7495  LocalContext context;
7496  context->Global()->Set(v8_str("o"), templ->NewInstance());
7497  for (int i = 0; i < 100; i++) {
7498  v8::HandleScope inner_scope(CcTest::isolate());
7499  v8::Handle<v8::Object> obj = templ->NewInstance();
7500  CHECK_NE(obj, context->Global()->Get(v8_str("o")));
7501  context->Global()->Set(v8_str("o2"), obj);
7502  v8::Handle<Value> value =
7503  CompileRun("o.__proto__ === o2.__proto__");
7504  CHECK_EQ(v8::True(isolate), value);
7505  context->Global()->Set(v8_str("o"), obj);
7506  }
7507 }
7508 
7509 
7510 static int StrCmp16(uint16_t* a, uint16_t* b) {
7511  while (true) {
7512  if (*a == 0 && *b == 0) return 0;
7513  if (*a != *b) return 0 + *a - *b;
7514  a++;
7515  b++;
7516  }
7517 }
7518 
7519 
7520 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
7521  while (true) {
7522  if (n-- == 0) return 0;
7523  if (*a == 0 && *b == 0) return 0;
7524  if (*a != *b) return 0 + *a - *b;
7525  a++;
7526  b++;
7527  }
7528 }
7529 
7530 
7531 int GetUtf8Length(Handle<String> str) {
7532  int len = str->Utf8Length();
7533  if (len < 0) {
7535  i::FlattenString(istr);
7536  len = str->Utf8Length();
7537  }
7538  return len;
7539 }
7540 
7541 
7542 THREADED_TEST(StringWrite) {
7543  LocalContext context;
7544  v8::HandleScope scope(context->GetIsolate());
7545  v8::Handle<String> str = v8_str("abcde");
7546  // abc<Icelandic eth><Unicode snowman>.
7547  v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
7549  context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
7550  // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
7551  uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
7553  context->GetIsolate(), orphans, v8::String::kNormalString, 8);
7554  // single lead surrogate
7555  uint16_t lead[1] = { 0xd800 };
7557  context->GetIsolate(), lead, v8::String::kNormalString, 1);
7558  // single trail surrogate
7559  uint16_t trail[1] = { 0xdc00 };
7561  context->GetIsolate(), trail, v8::String::kNormalString, 1);
7562  // surrogate pair
7563  uint16_t pair[2] = { 0xd800, 0xdc00 };
7565  context->GetIsolate(), pair, v8::String::kNormalString, 2);
7566  const int kStride = 4; // Must match stride in for loops in JS below.
7567  CompileRun(
7568  "var left = '';"
7569  "for (var i = 0; i < 0xd800; i += 4) {"
7570  " left = left + String.fromCharCode(i);"
7571  "}");
7572  CompileRun(
7573  "var right = '';"
7574  "for (var i = 0; i < 0xd800; i += 4) {"
7575  " right = String.fromCharCode(i) + right;"
7576  "}");
7577  v8::Handle<v8::Object> global = context->Global();
7578  Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7579  Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
7580 
7581  CHECK_EQ(5, str2->Length());
7582  CHECK_EQ(0xd800 / kStride, left_tree->Length());
7583  CHECK_EQ(0xd800 / kStride, right_tree->Length());
7584 
7585  char buf[100];
7586  char utf8buf[0xd800 * 3];
7587  uint16_t wbuf[100];
7588  int len;
7589  int charlen;
7590 
7591  memset(utf8buf, 0x1, 1000);
7592  len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7593  CHECK_EQ(9, len);
7594  CHECK_EQ(5, charlen);
7595  CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7596 
7597  memset(utf8buf, 0x1, 1000);
7598  len = str2->WriteUtf8(utf8buf, 8, &charlen);
7599  CHECK_EQ(8, len);
7600  CHECK_EQ(5, charlen);
7601  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
7602 
7603  memset(utf8buf, 0x1, 1000);
7604  len = str2->WriteUtf8(utf8buf, 7, &charlen);
7605  CHECK_EQ(5, len);
7606  CHECK_EQ(4, charlen);
7607  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7608 
7609  memset(utf8buf, 0x1, 1000);
7610  len = str2->WriteUtf8(utf8buf, 6, &charlen);
7611  CHECK_EQ(5, len);
7612  CHECK_EQ(4, charlen);
7613  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7614 
7615  memset(utf8buf, 0x1, 1000);
7616  len = str2->WriteUtf8(utf8buf, 5, &charlen);
7617  CHECK_EQ(5, len);
7618  CHECK_EQ(4, charlen);
7619  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7620 
7621  memset(utf8buf, 0x1, 1000);
7622  len = str2->WriteUtf8(utf8buf, 4, &charlen);
7623  CHECK_EQ(3, len);
7624  CHECK_EQ(3, charlen);
7625  CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7626 
7627  memset(utf8buf, 0x1, 1000);
7628  len = str2->WriteUtf8(utf8buf, 3, &charlen);
7629  CHECK_EQ(3, len);
7630  CHECK_EQ(3, charlen);
7631  CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7632 
7633  memset(utf8buf, 0x1, 1000);
7634  len = str2->WriteUtf8(utf8buf, 2, &charlen);
7635  CHECK_EQ(2, len);
7636  CHECK_EQ(2, charlen);
7637  CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
7638 
7639  // allow orphan surrogates by default
7640  memset(utf8buf, 0x1, 1000);
7641  len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7642  CHECK_EQ(13, len);
7643  CHECK_EQ(8, charlen);
7644  CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7645 
7646  // replace orphan surrogates with unicode replacement character
7647  memset(utf8buf, 0x1, 1000);
7648  len = orphans_str->WriteUtf8(utf8buf,
7649  sizeof(utf8buf),
7650  &charlen,
7651  String::REPLACE_INVALID_UTF8);
7652  CHECK_EQ(13, len);
7653  CHECK_EQ(8, charlen);
7654  CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7655 
7656  // replace single lead surrogate with unicode replacement character
7657  memset(utf8buf, 0x1, 1000);
7658  len = lead_str->WriteUtf8(utf8buf,
7659  sizeof(utf8buf),
7660  &charlen,
7661  String::REPLACE_INVALID_UTF8);
7662  CHECK_EQ(4, len);
7663  CHECK_EQ(1, charlen);
7664  CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7665 
7666  // replace single trail surrogate with unicode replacement character
7667  memset(utf8buf, 0x1, 1000);
7668  len = trail_str->WriteUtf8(utf8buf,
7669  sizeof(utf8buf),
7670  &charlen,
7671  String::REPLACE_INVALID_UTF8);
7672  CHECK_EQ(4, len);
7673  CHECK_EQ(1, charlen);
7674  CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7675 
7676  // do not replace / write anything if surrogate pair does not fit the buffer
7677  // space
7678  memset(utf8buf, 0x1, 1000);
7679  len = pair_str->WriteUtf8(utf8buf,
7680  3,
7681  &charlen,
7682  String::REPLACE_INVALID_UTF8);
7683  CHECK_EQ(0, len);
7684  CHECK_EQ(0, charlen);
7685 
7686  memset(utf8buf, 0x1, sizeof(utf8buf));
7687  len = GetUtf8Length(left_tree);
7688  int utf8_expected =
7689  (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7690  CHECK_EQ(utf8_expected, len);
7691  len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7692  CHECK_EQ(utf8_expected, len);
7693  CHECK_EQ(0xd800 / kStride, charlen);
7694  CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7695  CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7696  CHECK_EQ(0xc0 - kStride,
7697  static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7698  CHECK_EQ(1, utf8buf[utf8_expected]);
7699 
7700  memset(utf8buf, 0x1, sizeof(utf8buf));
7701  len = GetUtf8Length(right_tree);
7702  CHECK_EQ(utf8_expected, len);
7703  len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7704  CHECK_EQ(utf8_expected, len);
7705  CHECK_EQ(0xd800 / kStride, charlen);
7706  CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7707  CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7708  CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7709  CHECK_EQ(1, utf8buf[utf8_expected]);
7710 
7711  memset(buf, 0x1, sizeof(buf));
7712  memset(wbuf, 0x1, sizeof(wbuf));
7713  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7714  CHECK_EQ(5, len);
7715  len = str->Write(wbuf);
7716  CHECK_EQ(5, len);
7717  CHECK_EQ(0, strcmp("abcde", buf));
7718  uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7719  CHECK_EQ(0, StrCmp16(answer1, wbuf));
7720 
7721  memset(buf, 0x1, sizeof(buf));
7722  memset(wbuf, 0x1, sizeof(wbuf));
7723  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
7724  CHECK_EQ(4, len);
7725  len = str->Write(wbuf, 0, 4);
7726  CHECK_EQ(4, len);
7727  CHECK_EQ(0, strncmp("abcd\1", buf, 5));
7728  uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
7729  CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
7730 
7731  memset(buf, 0x1, sizeof(buf));
7732  memset(wbuf, 0x1, sizeof(wbuf));
7733  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
7734  CHECK_EQ(5, len);
7735  len = str->Write(wbuf, 0, 5);
7736  CHECK_EQ(5, len);
7737  CHECK_EQ(0, strncmp("abcde\1", buf, 6));
7738  uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
7739  CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
7740 
7741  memset(buf, 0x1, sizeof(buf));
7742  memset(wbuf, 0x1, sizeof(wbuf));
7743  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
7744  CHECK_EQ(5, len);
7745  len = str->Write(wbuf, 0, 6);
7746  CHECK_EQ(5, len);
7747  CHECK_EQ(0, strcmp("abcde", buf));
7748  uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7749  CHECK_EQ(0, StrCmp16(answer4, wbuf));
7750 
7751  memset(buf, 0x1, sizeof(buf));
7752  memset(wbuf, 0x1, sizeof(wbuf));
7753  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
7754  CHECK_EQ(1, len);
7755  len = str->Write(wbuf, 4, -1);
7756  CHECK_EQ(1, len);
7757  CHECK_EQ(0, strcmp("e", buf));
7758  uint16_t answer5[] = {'e', '\0'};
7759  CHECK_EQ(0, StrCmp16(answer5, wbuf));
7760 
7761  memset(buf, 0x1, sizeof(buf));
7762  memset(wbuf, 0x1, sizeof(wbuf));
7763  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
7764  CHECK_EQ(1, len);
7765  len = str->Write(wbuf, 4, 6);
7766  CHECK_EQ(1, len);
7767  CHECK_EQ(0, strcmp("e", buf));
7768  CHECK_EQ(0, StrCmp16(answer5, wbuf));
7769 
7770  memset(buf, 0x1, sizeof(buf));
7771  memset(wbuf, 0x1, sizeof(wbuf));
7772  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
7773  CHECK_EQ(1, len);
7774  len = str->Write(wbuf, 4, 1);
7775  CHECK_EQ(1, len);
7776  CHECK_EQ(0, strncmp("e\1", buf, 2));
7777  uint16_t answer6[] = {'e', 0x101};
7778  CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
7779 
7780  memset(buf, 0x1, sizeof(buf));
7781  memset(wbuf, 0x1, sizeof(wbuf));
7782  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
7783  CHECK_EQ(1, len);
7784  len = str->Write(wbuf, 3, 1);
7785  CHECK_EQ(1, len);
7786  CHECK_EQ(0, strncmp("d\1", buf, 2));
7787  uint16_t answer7[] = {'d', 0x101};
7788  CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
7789 
7790  memset(wbuf, 0x1, sizeof(wbuf));
7791  wbuf[5] = 'X';
7792  len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7793  CHECK_EQ(5, len);
7794  CHECK_EQ('X', wbuf[5]);
7795  uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7796  uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7797  CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7798  CHECK_NE(0, StrCmp16(answer8b, wbuf));
7799  wbuf[5] = '\0';
7800  CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7801 
7802  memset(buf, 0x1, sizeof(buf));
7803  buf[5] = 'X';
7804  len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7805  0,
7806  6,
7807  String::NO_NULL_TERMINATION);
7808  CHECK_EQ(5, len);
7809  CHECK_EQ('X', buf[5]);
7810  CHECK_EQ(0, strncmp("abcde", buf, 5));
7811  CHECK_NE(0, strcmp("abcde", buf));
7812  buf[5] = '\0';
7813  CHECK_EQ(0, strcmp("abcde", buf));
7814 
7815  memset(utf8buf, 0x1, sizeof(utf8buf));
7816  utf8buf[8] = 'X';
7817  len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7818  String::NO_NULL_TERMINATION);
7819  CHECK_EQ(8, len);
7820  CHECK_EQ('X', utf8buf[8]);
7821  CHECK_EQ(5, charlen);
7822  CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7823  CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7824  utf8buf[8] = '\0';
7825  CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7826 
7827  memset(utf8buf, 0x1, sizeof(utf8buf));
7828  utf8buf[5] = 'X';
7829  len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7830  String::NO_NULL_TERMINATION);
7831  CHECK_EQ(5, len);
7832  CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
7833  CHECK_EQ(5, charlen);
7834  utf8buf[5] = '\0';
7835  CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7836 
7837  memset(buf, 0x1, sizeof(buf));
7838  len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7839  CHECK_EQ(7, len);
7840  CHECK_EQ(0, strcmp("abc", buf));
7841  CHECK_EQ(0, buf[3]);
7842  CHECK_EQ(0, strcmp("def", buf + 4));
7843 
7844  CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
7845  CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7846  CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
7847 }
7848 
7849 
7850 static void Utf16Helper(
7851  LocalContext& context,
7852  const char* name,
7853  const char* lengths_name,
7854  int len) {
7855  Local<v8::Array> a =
7856  Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7857  Local<v8::Array> alens =
7858  Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7859  for (int i = 0; i < len; i++) {
7860  Local<v8::String> string =
7861  Local<v8::String>::Cast(a->Get(i));
7862  Local<v8::Number> expected_len =
7863  Local<v8::Number>::Cast(alens->Get(i));
7864  int length = GetUtf8Length(string);
7865  CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7866  }
7867 }
7868 
7869 
7870 static uint16_t StringGet(Handle<String> str, int index) {
7871  i::Handle<i::String> istring =
7872  v8::Utils::OpenHandle(String::Cast(*str));
7873  return istring->Get(index);
7874 }
7875 
7876 
7877 static void WriteUtf8Helper(
7878  LocalContext& context,
7879  const char* name,
7880  const char* lengths_name,
7881  int len) {
7882  Local<v8::Array> b =
7883  Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7884  Local<v8::Array> alens =
7885  Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7886  char buffer[1000];
7887  char buffer2[1000];
7888  for (int i = 0; i < len; i++) {
7889  Local<v8::String> string =
7890  Local<v8::String>::Cast(b->Get(i));
7891  Local<v8::Number> expected_len =
7892  Local<v8::Number>::Cast(alens->Get(i));
7893  int utf8_length = static_cast<int>(expected_len->Value());
7894  for (int j = utf8_length + 1; j >= 0; j--) {
7895  memset(reinterpret_cast<void*>(&buffer), 42, sizeof(buffer));
7896  memset(reinterpret_cast<void*>(&buffer2), 42, sizeof(buffer2));
7897  int nchars;
7898  int utf8_written =
7899  string->WriteUtf8(buffer, j, &nchars, String::NO_OPTIONS);
7900  int utf8_written2 =
7901  string->WriteUtf8(buffer2, j, &nchars, String::NO_NULL_TERMINATION);
7902  CHECK_GE(utf8_length + 1, utf8_written);
7903  CHECK_GE(utf8_length, utf8_written2);
7904  for (int k = 0; k < utf8_written2; k++) {
7905  CHECK_EQ(buffer[k], buffer2[k]);
7906  }
7907  CHECK(nchars * 3 >= utf8_written - 1);
7908  CHECK(nchars <= utf8_written);
7909  if (j == utf8_length + 1) {
7910  CHECK_EQ(utf8_written2, utf8_length);
7911  CHECK_EQ(utf8_written2 + 1, utf8_written);
7912  }
7913  CHECK_EQ(buffer[utf8_written], 42);
7914  if (j > utf8_length) {
7915  if (utf8_written != 0) CHECK_EQ(buffer[utf8_written - 1], 0);
7916  if (utf8_written > 1) CHECK_NE(buffer[utf8_written - 2], 42);
7917  Handle<String> roundtrip = v8_str(buffer);
7918  CHECK(roundtrip->Equals(string));
7919  } else {
7920  if (utf8_written != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7921  }
7922  if (utf8_written2 != 0) CHECK_NE(buffer[utf8_written - 1], 42);
7923  if (nchars >= 2) {
7924  uint16_t trail = StringGet(string, nchars - 1);
7925  uint16_t lead = StringGet(string, nchars - 2);
7926  if (((lead & 0xfc00) == 0xd800) &&
7927  ((trail & 0xfc00) == 0xdc00)) {
7928  unsigned char u1 = buffer2[utf8_written2 - 4];
7929  unsigned char u2 = buffer2[utf8_written2 - 3];
7930  unsigned char u3 = buffer2[utf8_written2 - 2];
7931  unsigned char u4 = buffer2[utf8_written2 - 1];
7932  CHECK_EQ((u1 & 0xf8), 0xf0);
7933  CHECK_EQ((u2 & 0xc0), 0x80);
7934  CHECK_EQ((u3 & 0xc0), 0x80);
7935  CHECK_EQ((u4 & 0xc0), 0x80);
7936  uint32_t c = 0x10000 + ((lead & 0x3ff) << 10) + (trail & 0x3ff);
7937  CHECK_EQ((u4 & 0x3f), (c & 0x3f));
7938  CHECK_EQ((u3 & 0x3f), ((c >> 6) & 0x3f));
7939  CHECK_EQ((u2 & 0x3f), ((c >> 12) & 0x3f));
7940  CHECK_EQ((u1 & 0x3), c >> 18);
7941  }
7942  }
7943  }
7944  }
7945 }
7946 
7947 
7949  LocalContext context;
7950  v8::HandleScope scope(context->GetIsolate());
7951  CompileRun(
7952  "var pad = '01234567890123456789';"
7953  "var p = [];"
7954  "var plens = [20, 3, 3];"
7955  "p.push('01234567890123456789');"
7956  "var lead = 0xd800;"
7957  "var trail = 0xdc00;"
7958  "p.push(String.fromCharCode(0xd800));"
7959  "p.push(String.fromCharCode(0xdc00));"
7960  "var a = [];"
7961  "var b = [];"
7962  "var c = [];"
7963  "var alens = [];"
7964  "for (var i = 0; i < 3; i++) {"
7965  " p[1] = String.fromCharCode(lead++);"
7966  " for (var j = 0; j < 3; j++) {"
7967  " p[2] = String.fromCharCode(trail++);"
7968  " a.push(p[i] + p[j]);"
7969  " b.push(p[i] + p[j]);"
7970  " c.push(p[i] + p[j]);"
7971  " alens.push(plens[i] + plens[j]);"
7972  " }"
7973  "}"
7974  "alens[5] -= 2;" // Here the surrogate pairs match up.
7975  "var a2 = [];"
7976  "var b2 = [];"
7977  "var c2 = [];"
7978  "var a2lens = [];"
7979  "for (var m = 0; m < 9; m++) {"
7980  " for (var n = 0; n < 9; n++) {"
7981  " a2.push(a[m] + a[n]);"
7982  " b2.push(b[m] + b[n]);"
7983  " var newc = 'x' + c[m] + c[n] + 'y';"
7984  " c2.push(newc.substring(1, newc.length - 1));"
7985  " var utf = alens[m] + alens[n];" // And here.
7986  // The 'n's that start with 0xdc.. are 6-8
7987  // The 'm's that end with 0xd8.. are 1, 4 and 7
7988  " if ((m % 3) == 1 && n >= 6) utf -= 2;"
7989  " a2lens.push(utf);"
7990  " }"
7991  "}");
7992  Utf16Helper(context, "a", "alens", 9);
7993  Utf16Helper(context, "a2", "a2lens", 81);
7994  WriteUtf8Helper(context, "b", "alens", 9);
7995  WriteUtf8Helper(context, "b2", "a2lens", 81);
7996  WriteUtf8Helper(context, "c2", "a2lens", 81);
7997 }
7998 
7999 
8000 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
8003  return *is1 == *is2;
8004 }
8005 
8006 static void SameSymbolHelper(v8::Isolate* isolate, const char* a,
8007  const char* b) {
8008  Handle<String> symbol1 =
8010  Handle<String> symbol2 =
8012  CHECK(SameSymbol(symbol1, symbol2));
8013 }
8014 
8015 
8016 THREADED_TEST(Utf16Symbol) {
8017  LocalContext context;
8018  v8::HandleScope scope(context->GetIsolate());
8019 
8020  Handle<String> symbol1 = v8::String::NewFromUtf8(
8021  context->GetIsolate(), "abc", v8::String::kInternalizedString);
8022  Handle<String> symbol2 = v8::String::NewFromUtf8(
8023  context->GetIsolate(), "abc", v8::String::kInternalizedString);
8024  CHECK(SameSymbol(symbol1, symbol2));
8025 
8026  SameSymbolHelper(context->GetIsolate(),
8027  "\360\220\220\205", // 4 byte encoding.
8028  "\355\240\201\355\260\205"); // 2 3-byte surrogates.
8029  SameSymbolHelper(context->GetIsolate(),
8030  "\355\240\201\355\260\206", // 2 3-byte surrogates.
8031  "\360\220\220\206"); // 4 byte encoding.
8032  SameSymbolHelper(context->GetIsolate(),
8033  "x\360\220\220\205", // 4 byte encoding.
8034  "x\355\240\201\355\260\205"); // 2 3-byte surrogates.
8035  SameSymbolHelper(context->GetIsolate(),
8036  "x\355\240\201\355\260\206", // 2 3-byte surrogates.
8037  "x\360\220\220\206"); // 4 byte encoding.
8038  CompileRun(
8039  "var sym0 = 'benedictus';"
8040  "var sym0b = 'S\303\270ren';"
8041  "var sym1 = '\355\240\201\355\260\207';"
8042  "var sym2 = '\360\220\220\210';"
8043  "var sym3 = 'x\355\240\201\355\260\207';"
8044  "var sym4 = 'x\360\220\220\210';"
8045  "if (sym1.length != 2) throw sym1;"
8046  "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
8047  "if (sym2.length != 2) throw sym2;"
8048  "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
8049  "if (sym3.length != 3) throw sym3;"
8050  "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
8051  "if (sym4.length != 3) throw sym4;"
8052  "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
8053  Handle<String> sym0 = v8::String::NewFromUtf8(
8054  context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
8055  Handle<String> sym0b = v8::String::NewFromUtf8(
8056  context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
8057  Handle<String> sym1 =
8058  v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
8060  Handle<String> sym2 =
8061  v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
8063  Handle<String> sym3 = v8::String::NewFromUtf8(
8064  context->GetIsolate(), "x\355\240\201\355\260\207",
8066  Handle<String> sym4 =
8067  v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
8069  v8::Local<v8::Object> global = context->Global();
8070  Local<Value> s0 = global->Get(v8_str("sym0"));
8071  Local<Value> s0b = global->Get(v8_str("sym0b"));
8072  Local<Value> s1 = global->Get(v8_str("sym1"));
8073  Local<Value> s2 = global->Get(v8_str("sym2"));
8074  Local<Value> s3 = global->Get(v8_str("sym3"));
8075  Local<Value> s4 = global->Get(v8_str("sym4"));
8076  CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
8077  CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
8078  CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
8079  CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
8080  CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
8081  CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
8082 }
8083 
8084 
8085 THREADED_TEST(ToArrayIndex) {
8086  LocalContext context;
8087  v8::Isolate* isolate = context->GetIsolate();
8088  v8::HandleScope scope(isolate);
8089 
8090  v8::Handle<String> str = v8_str("42");
8091  v8::Handle<v8::Uint32> index = str->ToArrayIndex();
8092  CHECK(!index.IsEmpty());
8093  CHECK_EQ(42.0, index->Uint32Value());
8094  str = v8_str("42asdf");
8095  index = str->ToArrayIndex();
8096  CHECK(index.IsEmpty());
8097  str = v8_str("-42");
8098  index = str->ToArrayIndex();
8099  CHECK(index.IsEmpty());
8100  str = v8_str("4294967295");
8101  index = str->ToArrayIndex();
8102  CHECK(!index.IsEmpty());
8103  CHECK_EQ(4294967295.0, index->Uint32Value());
8104  v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
8105  index = num->ToArrayIndex();
8106  CHECK(!index.IsEmpty());
8107  CHECK_EQ(1.0, index->Uint32Value());
8108  num = v8::Number::New(isolate, -1);
8109  index = num->ToArrayIndex();
8110  CHECK(index.IsEmpty());
8111  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
8112  index = obj->ToArrayIndex();
8113  CHECK(index.IsEmpty());
8114 }
8115 
8116 
8117 THREADED_TEST(ErrorConstruction) {
8118  LocalContext context;
8119  v8::HandleScope scope(context->GetIsolate());
8120 
8121  v8::Handle<String> foo = v8_str("foo");
8122  v8::Handle<String> message = v8_str("message");
8123  v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
8124  CHECK(range_error->IsObject());
8125  CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
8126  v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
8127  CHECK(reference_error->IsObject());
8128  CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
8129  v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
8130  CHECK(syntax_error->IsObject());
8131  CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
8132  v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
8133  CHECK(type_error->IsObject());
8134  CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
8136  CHECK(error->IsObject());
8137  CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
8138 }
8139 
8140 
8141 static void YGetter(Local<String> name,
8144  info.GetReturnValue().Set(v8_num(10));
8145 }
8146 
8147 
8148 static void YSetter(Local<String> name,
8149  Local<Value> value,
8150  const v8::PropertyCallbackInfo<void>& info) {
8151  if (info.This()->Has(name)) {
8152  info.This()->Delete(name);
8153  }
8154  info.This()->Set(name, value);
8155 }
8156 
8157 
8158 THREADED_TEST(DeleteAccessor) {
8159  v8::Isolate* isolate = CcTest::isolate();
8160  v8::HandleScope scope(isolate);
8161  v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
8162  obj->SetAccessor(v8_str("y"), YGetter, YSetter);
8163  LocalContext context;
8164  v8::Handle<v8::Object> holder = obj->NewInstance();
8165  context->Global()->Set(v8_str("holder"), holder);
8166  v8::Handle<Value> result = CompileRun(
8167  "holder.y = 11; holder.y = 12; holder.y");
8168  CHECK_EQ(12, result->Uint32Value());
8169 }
8170 
8171 
8172 THREADED_TEST(TypeSwitch) {
8173  v8::Isolate* isolate = CcTest::isolate();
8174  v8::HandleScope scope(isolate);
8178  v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
8179  v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
8180  LocalContext context;
8181  v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
8182  v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
8183  v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
8184  v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
8185  for (int i = 0; i < 10; i++) {
8186  CHECK_EQ(0, type_switch->match(obj0));
8187  CHECK_EQ(1, type_switch->match(obj1));
8188  CHECK_EQ(2, type_switch->match(obj2));
8189  CHECK_EQ(3, type_switch->match(obj3));
8190  CHECK_EQ(3, type_switch->match(obj3));
8191  CHECK_EQ(2, type_switch->match(obj2));
8192  CHECK_EQ(1, type_switch->match(obj1));
8193  CHECK_EQ(0, type_switch->match(obj0));
8194  }
8195 }
8196 
8197 
8198 // For use within the TestSecurityHandler() test.
8199 static bool g_security_callback_result = false;
8200 static bool NamedSecurityTestCallback(Local<v8::Object> global,
8201  Local<Value> name,
8202  v8::AccessType type,
8203  Local<Value> data) {
8204  // Always allow read access.
8205  if (type == v8::ACCESS_GET)
8206  return true;
8207 
8208  // Sometimes allow other access.
8209  return g_security_callback_result;
8210 }
8211 
8212 
8213 static bool IndexedSecurityTestCallback(Local<v8::Object> global,
8214  uint32_t key,
8215  v8::AccessType type,
8216  Local<Value> data) {
8217  // Always allow read access.
8218  if (type == v8::ACCESS_GET)
8219  return true;
8220 
8221  // Sometimes allow other access.
8222  return g_security_callback_result;
8223 }
8224 
8225 
8226 static int trouble_nesting = 0;
8227 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
8229  trouble_nesting++;
8230 
8231  // Call a JS function that throws an uncaught exception.
8232  Local<v8::Object> arg_this =
8233  args.GetIsolate()->GetCurrentContext()->Global();
8234  Local<Value> trouble_callee = (trouble_nesting == 3) ?
8235  arg_this->Get(v8_str("trouble_callee")) :
8236  arg_this->Get(v8_str("trouble_caller"));
8237  CHECK(trouble_callee->IsFunction());
8238  args.GetReturnValue().Set(
8239  Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
8240 }
8241 
8242 
8243 static int report_count = 0;
8244 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
8246  report_count++;
8247 }
8248 
8249 
8250 // Counts uncaught exceptions, but other tests running in parallel
8251 // also have uncaught exceptions.
8252 TEST(ApiUncaughtException) {
8253  report_count = 0;
8254  LocalContext env;
8255  v8::Isolate* isolate = env->GetIsolate();
8256  v8::HandleScope scope(isolate);
8257  v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
8258 
8259  Local<v8::FunctionTemplate> fun =
8260  v8::FunctionTemplate::New(isolate, TroubleCallback);
8261  v8::Local<v8::Object> global = env->Global();
8262  global->Set(v8_str("trouble"), fun->GetFunction());
8263 
8264  CompileRun(
8265  "function trouble_callee() {"
8266  " var x = null;"
8267  " return x.foo;"
8268  "};"
8269  "function trouble_caller() {"
8270  " trouble();"
8271  "};");
8272  Local<Value> trouble = global->Get(v8_str("trouble"));
8273  CHECK(trouble->IsFunction());
8274  Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
8275  CHECK(trouble_callee->IsFunction());
8276  Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
8277  CHECK(trouble_caller->IsFunction());
8278  Function::Cast(*trouble_caller)->Call(global, 0, NULL);
8279  CHECK_EQ(1, report_count);
8280  v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
8281 }
8282 
8283 static const char* script_resource_name = "ExceptionInNativeScript.js";
8284 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
8286  v8::Handle<v8::Value> name_val = message->GetScriptResourceName();
8287  CHECK(!name_val.IsEmpty() && name_val->IsString());
8289  CHECK_EQ(script_resource_name, *name);
8290  CHECK_EQ(3, message->GetLineNumber());
8291  v8::String::Utf8Value source_line(message->GetSourceLine());
8292  CHECK_EQ(" new o.foo();", *source_line);
8293 }
8294 
8295 
8296 TEST(ExceptionInNativeScript) {
8297  LocalContext env;
8298  v8::Isolate* isolate = env->GetIsolate();
8299  v8::HandleScope scope(isolate);
8300  v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
8301 
8302  Local<v8::FunctionTemplate> fun =
8303  v8::FunctionTemplate::New(isolate, TroubleCallback);
8304  v8::Local<v8::Object> global = env->Global();
8305  global->Set(v8_str("trouble"), fun->GetFunction());
8306 
8307  CompileRunWithOrigin(
8308  "function trouble() {\n"
8309  " var o = {};\n"
8310  " new o.foo();\n"
8311  "};",
8312  script_resource_name);
8313  Local<Value> trouble = global->Get(v8_str("trouble"));
8314  CHECK(trouble->IsFunction());
8315  Function::Cast(*trouble)->Call(global, 0, NULL);
8316  v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
8317 }
8318 
8319 
8320 TEST(CompilationErrorUsingTryCatchHandler) {
8321  LocalContext env;
8322  v8::HandleScope scope(env->GetIsolate());
8323  v8::TryCatch try_catch;
8324  v8_compile("This doesn't &*&@#$&*^ compile.");
8325  CHECK_NE(NULL, *try_catch.Exception());
8326  CHECK(try_catch.HasCaught());
8327 }
8328 
8329 
8330 TEST(TryCatchFinallyUsingTryCatchHandler) {
8331  LocalContext env;
8332  v8::HandleScope scope(env->GetIsolate());
8333  v8::TryCatch try_catch;
8334  CompileRun("try { throw ''; } catch (e) {}");
8335  CHECK(!try_catch.HasCaught());
8336  CompileRun("try { throw ''; } finally {}");
8337  CHECK(try_catch.HasCaught());
8338  try_catch.Reset();
8339  CompileRun(
8340  "(function() {"
8341  "try { throw ''; } finally { return; }"
8342  "})()");
8343  CHECK(!try_catch.HasCaught());
8344  CompileRun(
8345  "(function()"
8346  " { try { throw ''; } finally { throw 0; }"
8347  "})()");
8348  CHECK(try_catch.HasCaught());
8349 }
8350 
8351 
8352 // SecurityHandler can't be run twice
8353 TEST(SecurityHandler) {
8354  v8::Isolate* isolate = CcTest::isolate();
8355  v8::HandleScope scope0(isolate);
8356  v8::Handle<v8::ObjectTemplate> global_template =
8357  v8::ObjectTemplate::New(isolate);
8358  global_template->SetAccessCheckCallbacks(NamedSecurityTestCallback,
8359  IndexedSecurityTestCallback);
8360  // Create an environment
8361  v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
8362  context0->Enter();
8363 
8364  v8::Handle<v8::Object> global0 = context0->Global();
8365  v8::Handle<Script> script0 = v8_compile("foo = 111");
8366  script0->Run();
8367  global0->Set(v8_str("0"), v8_num(999));
8368  v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
8369  CHECK_EQ(111, foo0->Int32Value());
8370  v8::Handle<Value> z0 = global0->Get(v8_str("0"));
8371  CHECK_EQ(999, z0->Int32Value());
8372 
8373  // Create another environment, should fail security checks.
8374  v8::HandleScope scope1(isolate);
8375 
8376  v8::Handle<Context> context1 =
8377  Context::New(isolate, NULL, global_template);
8378  context1->Enter();
8379 
8380  v8::Handle<v8::Object> global1 = context1->Global();
8381  global1->Set(v8_str("othercontext"), global0);
8382  // This set will fail the security check.
8383  v8::Handle<Script> script1 =
8384  v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
8385  script1->Run();
8386  // This read will pass the security check.
8387  v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
8388  CHECK_EQ(111, foo1->Int32Value());
8389  // This read will pass the security check.
8390  v8::Handle<Value> z1 = global0->Get(v8_str("0"));
8391  CHECK_EQ(999, z1->Int32Value());
8392 
8393  // Create another environment, should pass security checks.
8394  { g_security_callback_result = true; // allow security handler to pass.
8395  v8::HandleScope scope2(isolate);
8396  LocalContext context2;
8397  v8::Handle<v8::Object> global2 = context2->Global();
8398  global2->Set(v8_str("othercontext"), global0);
8399  v8::Handle<Script> script2 =
8400  v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
8401  script2->Run();
8402  v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
8403  CHECK_EQ(333, foo2->Int32Value());
8404  v8::Handle<Value> z2 = global0->Get(v8_str("0"));
8405  CHECK_EQ(888, z2->Int32Value());
8406  }
8407 
8408  context1->Exit();
8409  context0->Exit();
8410 }
8411 
8412 
8413 THREADED_TEST(SecurityChecks) {
8414  LocalContext env1;
8415  v8::HandleScope handle_scope(env1->GetIsolate());
8416  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8417 
8418  Local<Value> foo = v8_str("foo");
8419  Local<Value> bar = v8_str("bar");
8420 
8421  // Set to the same domain.
8422  env1->SetSecurityToken(foo);
8423 
8424  // Create a function in env1.
8425  CompileRun("spy=function(){return spy;}");
8426  Local<Value> spy = env1->Global()->Get(v8_str("spy"));
8427  CHECK(spy->IsFunction());
8428 
8429  // Create another function accessing global objects.
8430  CompileRun("spy2=function(){return new this.Array();}");
8431  Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
8432  CHECK(spy2->IsFunction());
8433 
8434  // Switch to env2 in the same domain and invoke spy on env2.
8435  {
8436  env2->SetSecurityToken(foo);
8437  // Enter env2
8438  Context::Scope scope_env2(env2);
8439  Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
8440  CHECK(result->IsFunction());
8441  }
8442 
8443  {
8444  env2->SetSecurityToken(bar);
8445  Context::Scope scope_env2(env2);
8446 
8447  // Call cross_domain_call, it should throw an exception
8448  v8::TryCatch try_catch;
8449  Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
8450  CHECK(try_catch.HasCaught());
8451  }
8452 }
8453 
8454 
8455 // Regression test case for issue 1183439.
8456 THREADED_TEST(SecurityChecksForPrototypeChain) {
8457  LocalContext current;
8458  v8::HandleScope scope(current->GetIsolate());
8459  v8::Handle<Context> other = Context::New(current->GetIsolate());
8460 
8461  // Change context to be able to get to the Object function in the
8462  // other context without hitting the security checks.
8463  v8::Local<Value> other_object;
8464  { Context::Scope scope(other);
8465  other_object = other->Global()->Get(v8_str("Object"));
8466  other->Global()->Set(v8_num(42), v8_num(87));
8467  }
8468 
8469  current->Global()->Set(v8_str("other"), other->Global());
8470  CHECK(v8_compile("other")->Run()->Equals(other->Global()));
8471 
8472  // Make sure the security check fails here and we get an undefined
8473  // result instead of getting the Object function. Repeat in a loop
8474  // to make sure to exercise the IC code.
8475  v8::Local<Script> access_other0 = v8_compile("other.Object");
8476  v8::Local<Script> access_other1 = v8_compile("other[42]");
8477  for (int i = 0; i < 5; i++) {
8478  CHECK(!access_other0->Run()->Equals(other_object));
8479  CHECK(access_other0->Run()->IsUndefined());
8480  CHECK(!access_other1->Run()->Equals(v8_num(87)));
8481  CHECK(access_other1->Run()->IsUndefined());
8482  }
8483 
8484  // Create an object that has 'other' in its prototype chain and make
8485  // sure we cannot access the Object function indirectly through
8486  // that. Repeat in a loop to make sure to exercise the IC code.
8487  v8_compile("function F() { };"
8488  "F.prototype = other;"
8489  "var f = new F();")->Run();
8490  v8::Local<Script> access_f0 = v8_compile("f.Object");
8491  v8::Local<Script> access_f1 = v8_compile("f[42]");
8492  for (int j = 0; j < 5; j++) {
8493  CHECK(!access_f0->Run()->Equals(other_object));
8494  CHECK(access_f0->Run()->IsUndefined());
8495  CHECK(!access_f1->Run()->Equals(v8_num(87)));
8496  CHECK(access_f1->Run()->IsUndefined());
8497  }
8498 
8499  // Now it gets hairy: Set the prototype for the other global object
8500  // to be the current global object. The prototype chain for 'f' now
8501  // goes through 'other' but ends up in the current global object.
8502  { Context::Scope scope(other);
8503  other->Global()->Set(v8_str("__proto__"), current->Global());
8504  }
8505  // Set a named and an index property on the current global
8506  // object. To force the lookup to go through the other global object,
8507  // the properties must not exist in the other global object.
8508  current->Global()->Set(v8_str("foo"), v8_num(100));
8509  current->Global()->Set(v8_num(99), v8_num(101));
8510  // Try to read the properties from f and make sure that the access
8511  // gets stopped by the security checks on the other global object.
8512  Local<Script> access_f2 = v8_compile("f.foo");
8513  Local<Script> access_f3 = v8_compile("f[99]");
8514  for (int k = 0; k < 5; k++) {
8515  CHECK(!access_f2->Run()->Equals(v8_num(100)));
8516  CHECK(access_f2->Run()->IsUndefined());
8517  CHECK(!access_f3->Run()->Equals(v8_num(101)));
8518  CHECK(access_f3->Run()->IsUndefined());
8519  }
8520 }
8521 
8522 
8523 THREADED_TEST(CrossDomainDelete) {
8524  LocalContext env1;
8525  v8::HandleScope handle_scope(env1->GetIsolate());
8526  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8527 
8528  Local<Value> foo = v8_str("foo");
8529  Local<Value> bar = v8_str("bar");
8530 
8531  // Set to the same domain.
8532  env1->SetSecurityToken(foo);
8533  env2->SetSecurityToken(foo);
8534 
8535  env1->Global()->Set(v8_str("prop"), v8_num(3));
8536  env2->Global()->Set(v8_str("env1"), env1->Global());
8537 
8538  // Change env2 to a different domain and delete env1.prop.
8539  env2->SetSecurityToken(bar);
8540  {
8541  Context::Scope scope_env2(env2);
8542  Local<Value> result =
8543  CompileRun("delete env1.prop");
8544  CHECK(result->IsFalse());
8545  }
8546 
8547  // Check that env1.prop still exists.
8548  Local<Value> v = env1->Global()->Get(v8_str("prop"));
8549  CHECK(v->IsNumber());
8550  CHECK_EQ(3, v->Int32Value());
8551 }
8552 
8553 
8554 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
8555  LocalContext env1;
8556  v8::HandleScope handle_scope(env1->GetIsolate());
8557  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8558 
8559  Local<Value> foo = v8_str("foo");
8560  Local<Value> bar = v8_str("bar");
8561 
8562  // Set to the same domain.
8563  env1->SetSecurityToken(foo);
8564  env2->SetSecurityToken(foo);
8565 
8566  env1->Global()->Set(v8_str("prop"), v8_num(3));
8567  env2->Global()->Set(v8_str("env1"), env1->Global());
8568 
8569  // env1.prop is enumerable in env2.
8570  Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8571  {
8572  Context::Scope scope_env2(env2);
8573  Local<Value> result = CompileRun(test);
8574  CHECK(result->IsTrue());
8575  }
8576 
8577  // Change env2 to a different domain and test again.
8578  env2->SetSecurityToken(bar);
8579  {
8580  Context::Scope scope_env2(env2);
8581  Local<Value> result = CompileRun(test);
8582  CHECK(result->IsFalse());
8583  }
8584 }
8585 
8586 
8587 THREADED_TEST(CrossDomainForIn) {
8588  LocalContext env1;
8589  v8::HandleScope handle_scope(env1->GetIsolate());
8590  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8591 
8592  Local<Value> foo = v8_str("foo");
8593  Local<Value> bar = v8_str("bar");
8594 
8595  // Set to the same domain.
8596  env1->SetSecurityToken(foo);
8597  env2->SetSecurityToken(foo);
8598 
8599  env1->Global()->Set(v8_str("prop"), v8_num(3));
8600  env2->Global()->Set(v8_str("env1"), env1->Global());
8601 
8602  // Change env2 to a different domain and set env1's global object
8603  // as the __proto__ of an object in env2 and enumerate properties
8604  // in for-in. It shouldn't enumerate properties on env1's global
8605  // object.
8606  env2->SetSecurityToken(bar);
8607  {
8608  Context::Scope scope_env2(env2);
8609  Local<Value> result =
8610  CompileRun("(function(){var obj = {'__proto__':env1};"
8611  "for (var p in obj)"
8612  " if (p == 'prop') return false;"
8613  "return true;})()");
8614  CHECK(result->IsTrue());
8615  }
8616 }
8617 
8618 
8619 TEST(ContextDetachGlobal) {
8620  LocalContext env1;
8621  v8::HandleScope handle_scope(env1->GetIsolate());
8622  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8623 
8624  Local<v8::Object> global1 = env1->Global();
8625 
8626  Local<Value> foo = v8_str("foo");
8627 
8628  // Set to the same domain.
8629  env1->SetSecurityToken(foo);
8630  env2->SetSecurityToken(foo);
8631 
8632  // Enter env2
8633  env2->Enter();
8634 
8635  // Create a function in env2 and add a reference to it in env1.
8636  Local<v8::Object> global2 = env2->Global();
8637  global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
8638  CompileRun("function getProp() {return prop;}");
8639 
8640  env1->Global()->Set(v8_str("getProp"),
8641  global2->Get(v8_str("getProp")));
8642 
8643  // Detach env2's global, and reuse the global object of env2
8644  env2->Exit();
8645  env2->DetachGlobal();
8646 
8647  v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8648  0,
8650  global2);
8651  env3->SetSecurityToken(v8_str("bar"));
8652  env3->Enter();
8653 
8654  Local<v8::Object> global3 = env3->Global();
8655  CHECK_EQ(global2, global3);
8656  CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8657  CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
8658  global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8659  global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
8660  env3->Exit();
8661 
8662  // Call getProp in env1, and it should return the value 1
8663  {
8664  Local<Value> get_prop = global1->Get(v8_str("getProp"));
8665  CHECK(get_prop->IsFunction());
8666  v8::TryCatch try_catch;
8667  Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8668  CHECK(!try_catch.HasCaught());
8669  CHECK_EQ(1, r->Int32Value());
8670  }
8671 
8672  // Check that env3 is not accessible from env1
8673  {
8674  Local<Value> r = global3->Get(v8_str("prop2"));
8675  CHECK(r->IsUndefined());
8676  }
8677 }
8678 
8679 
8680 TEST(DetachGlobal) {
8681  LocalContext env1;
8682  v8::HandleScope scope(env1->GetIsolate());
8683 
8684  // Create second environment.
8685  v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8686 
8687  Local<Value> foo = v8_str("foo");
8688 
8689  // Set same security token for env1 and env2.
8690  env1->SetSecurityToken(foo);
8691  env2->SetSecurityToken(foo);
8692 
8693  // Create a property on the global object in env2.
8694  {
8695  v8::Context::Scope scope(env2);
8696  env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
8697  }
8698 
8699  // Create a reference to env2 global from env1 global.
8700  env1->Global()->Set(v8_str("other"), env2->Global());
8701 
8702  // Check that we have access to other.p in env2 from env1.
8703  Local<Value> result = CompileRun("other.p");
8704  CHECK(result->IsInt32());
8705  CHECK_EQ(42, result->Int32Value());
8706 
8707  // Hold on to global from env2 and detach global from env2.
8708  Local<v8::Object> global2 = env2->Global();
8709  env2->DetachGlobal();
8710 
8711  // Check that the global has been detached. No other.p property can
8712  // be found.
8713  result = CompileRun("other.p");
8714  CHECK(result->IsUndefined());
8715 
8716  // Reuse global2 for env3.
8717  v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8718  0,
8720  global2);
8721  CHECK_EQ(global2, env3->Global());
8722 
8723  // Start by using the same security token for env3 as for env1 and env2.
8724  env3->SetSecurityToken(foo);
8725 
8726  // Create a property on the global object in env3.
8727  {
8728  v8::Context::Scope scope(env3);
8729  env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
8730  }
8731 
8732  // Check that other.p is now the property in env3 and that we have access.
8733  result = CompileRun("other.p");
8734  CHECK(result->IsInt32());
8735  CHECK_EQ(24, result->Int32Value());
8736 
8737  // Change security token for env3 to something different from env1 and env2.
8738  env3->SetSecurityToken(v8_str("bar"));
8739 
8740  // Check that we do not have access to other.p in env1. |other| is now
8741  // the global object for env3 which has a different security token,
8742  // so access should be blocked.
8743  result = CompileRun("other.p");
8744  CHECK(result->IsUndefined());
8745 }
8746 
8747 
8749  info.GetReturnValue().Set(
8750  info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8751 }
8752 
8753 
8754 TEST(DetachedAccesses) {
8755  LocalContext env1;
8756  v8::HandleScope scope(env1->GetIsolate());
8757 
8758  // Create second environment.
8759  Local<ObjectTemplate> inner_global_template =
8760  FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8761  inner_global_template ->SetAccessorProperty(
8762  v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8763  v8::Local<Context> env2 =
8764  Context::New(env1->GetIsolate(), NULL, inner_global_template);
8765 
8766  Local<Value> foo = v8_str("foo");
8767 
8768  // Set same security token for env1 and env2.
8769  env1->SetSecurityToken(foo);
8770  env2->SetSecurityToken(foo);
8771 
8772  env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8773 
8774  {
8775  v8::Context::Scope scope(env2);
8776  env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
8777  CompileRun(
8778  "function bound_x() { return x; }"
8779  "function get_x() { return this.x; }"
8780  "function get_x_w() { return (function() {return this.x;})(); }");
8781  env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
8782  env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8783  env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
8784  env1->Global()->Set(
8785  v8_str("this_x"),
8786  CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
8787  }
8788 
8789  Local<Object> env2_global = env2->Global();
8790  env2_global->TurnOnAccessCheck();
8791  env2->DetachGlobal();
8792 
8793  Local<Value> result;
8794  result = CompileRun("bound_x()");
8795  CHECK_EQ(v8_str("env2_x"), result);
8796  result = CompileRun("get_x()");
8797  CHECK(result->IsUndefined());
8798  result = CompileRun("get_x_w()");
8799  CHECK(result->IsUndefined());
8800  result = CompileRun("this_x()");
8801  CHECK_EQ(v8_str("env2_x"), result);
8802 
8803  // Reattach env2's proxy
8804  env2 = Context::New(env1->GetIsolate(),
8805  0,
8807  env2_global);
8808  env2->SetSecurityToken(foo);
8809  {
8810  v8::Context::Scope scope(env2);
8811  env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8812  env2->Global()->Set(v8_str("env1"), env1->Global());
8813  result = CompileRun(
8814  "results = [];"
8815  "for (var i = 0; i < 4; i++ ) {"
8816  " results.push(env1.bound_x());"
8817  " results.push(env1.get_x());"
8818  " results.push(env1.get_x_w());"
8819  " results.push(env1.this_x());"
8820  "}"
8821  "results");
8822  Local<v8::Array> results = Local<v8::Array>::Cast(result);
8823  CHECK_EQ(16, results->Length());
8824  for (int i = 0; i < 16; i += 4) {
8825  CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8826  CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8827  CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8828  CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8829  }
8830  }
8831 
8832  result = CompileRun(
8833  "results = [];"
8834  "for (var i = 0; i < 4; i++ ) {"
8835  " results.push(bound_x());"
8836  " results.push(get_x());"
8837  " results.push(get_x_w());"
8838  " results.push(this_x());"
8839  "}"
8840  "results");
8841  Local<v8::Array> results = Local<v8::Array>::Cast(result);
8842  CHECK_EQ(16, results->Length());
8843  for (int i = 0; i < 16; i += 4) {
8844  CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8845  CHECK_EQ(v8_str("env3_x"), results->Get(i + 1));
8846  CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8847  CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8848  }
8849 
8850  result = CompileRun(
8851  "results = [];"
8852  "for (var i = 0; i < 4; i++ ) {"
8853  " results.push(this.bound_x());"
8854  " results.push(this.get_x());"
8855  " results.push(this.get_x_w());"
8856  " results.push(this.this_x());"
8857  "}"
8858  "results");
8859  results = Local<v8::Array>::Cast(result);
8860  CHECK_EQ(16, results->Length());
8861  for (int i = 0; i < 16; i += 4) {
8862  CHECK_EQ(v8_str("env2_x"), results->Get(i + 0));
8863  CHECK_EQ(v8_str("env1_x"), results->Get(i + 1));
8864  CHECK_EQ(v8_str("env3_x"), results->Get(i + 2));
8865  CHECK_EQ(v8_str("env2_x"), results->Get(i + 3));
8866  }
8867 }
8868 
8869 
8870 static bool allowed_access_type[v8::ACCESS_KEYS + 1] = { false };
8871 static bool NamedAccessBlocker(Local<v8::Object> global,
8872  Local<Value> name,
8873  v8::AccessType type,
8874  Local<Value> data) {
8875  return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
8876  allowed_access_type[type];
8877 }
8878 
8879 
8880 static bool IndexedAccessBlocker(Local<v8::Object> global,
8881  uint32_t key,
8882  v8::AccessType type,
8883  Local<Value> data) {
8884  return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
8885  allowed_access_type[type];
8886 }
8887 
8888 
8889 static int g_echo_value_1 = -1;
8890 static int g_echo_value_2 = -1;
8891 
8892 
8893 static void EchoGetter(
8894  Local<String> name,
8896  info.GetReturnValue().Set(v8_num(g_echo_value_1));
8897 }
8898 
8899 
8900 static void EchoGetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8901  info.GetReturnValue().Set(v8_num(g_echo_value_2));
8902 }
8903 
8904 
8905 static void EchoSetter(Local<String> name,
8906  Local<Value> value,
8908  if (value->IsNumber())
8909  g_echo_value_1 = value->Int32Value();
8910 }
8911 
8912 
8913 static void EchoSetter(const v8::FunctionCallbackInfo<v8::Value>& info) {
8914  v8::Handle<v8::Value> value = info[0];
8915  if (value->IsNumber())
8916  g_echo_value_2 = value->Int32Value();
8917 }
8918 
8919 
8920 static void UnreachableGetter(
8921  Local<String> name,
8923  CHECK(false); // This function should not be called..
8924 }
8925 
8926 
8927 static void UnreachableSetter(Local<String>,
8928  Local<Value>,
8930  CHECK(false); // This function should nto be called.
8931 }
8932 
8933 
8934 static void UnreachableFunction(
8936  CHECK(false); // This function should not be called..
8937 }
8938 
8939 
8941  v8::Isolate* isolate = CcTest::isolate();
8942  v8::HandleScope handle_scope(isolate);
8943  v8::Handle<v8::ObjectTemplate> global_template =
8944  v8::ObjectTemplate::New(isolate);
8945 
8946  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
8947  IndexedAccessBlocker);
8948 
8949  // Add an accessor accessible by cross-domain JS code.
8950  global_template->SetAccessor(
8951  v8_str("accessible_prop"),
8952  EchoGetter, EchoSetter,
8955 
8956 
8957  global_template->SetAccessorProperty(
8958  v8_str("accessible_js_prop"),
8959  v8::FunctionTemplate::New(isolate, EchoGetter),
8960  v8::FunctionTemplate::New(isolate, EchoSetter),
8961  v8::None,
8963 
8964  // Add an accessor that is not accessible by cross-domain JS code.
8965  global_template->SetAccessor(v8_str("blocked_prop"),
8966  UnreachableGetter, UnreachableSetter,
8968  v8::DEFAULT);
8969 
8970  global_template->SetAccessorProperty(
8971  v8_str("blocked_js_prop"),
8972  v8::FunctionTemplate::New(isolate, UnreachableFunction),
8973  v8::FunctionTemplate::New(isolate, UnreachableFunction),
8974  v8::None,
8975  v8::DEFAULT);
8976 
8977  // Create an environment
8978  v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8979  context0->Enter();
8980 
8981  v8::Handle<v8::Object> global0 = context0->Global();
8982 
8983  // Define a property with JS getter and setter.
8984  CompileRun(
8985  "function getter() { return 'getter'; };\n"
8986  "function setter() { return 'setter'; }\n"
8987  "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8988 
8989  Local<Value> getter = global0->Get(v8_str("getter"));
8990  Local<Value> setter = global0->Get(v8_str("setter"));
8991 
8992  // And define normal element.
8993  global0->Set(239, v8_str("239"));
8994 
8995  // Define an element with JS getter and setter.
8996  CompileRun(
8997  "function el_getter() { return 'el_getter'; };\n"
8998  "function el_setter() { return 'el_setter'; };\n"
8999  "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
9000 
9001  Local<Value> el_getter = global0->Get(v8_str("el_getter"));
9002  Local<Value> el_setter = global0->Get(v8_str("el_setter"));
9003 
9004  v8::HandleScope scope1(isolate);
9005 
9006  v8::Local<Context> context1 = Context::New(isolate);
9007  context1->Enter();
9008 
9009  v8::Handle<v8::Object> global1 = context1->Global();
9010  global1->Set(v8_str("other"), global0);
9011 
9012  // Access blocked property.
9013  CompileRun("other.blocked_prop = 1");
9014 
9015  ExpectUndefined("other.blocked_prop");
9016  ExpectUndefined(
9017  "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9018  ExpectFalse("propertyIsEnumerable.call(other, 'blocked_prop')");
9019 
9020  // Enable ACCESS_HAS
9021  allowed_access_type[v8::ACCESS_HAS] = true;
9022  ExpectUndefined("other.blocked_prop");
9023  // ... and now we can get the descriptor...
9024  ExpectUndefined(
9025  "Object.getOwnPropertyDescriptor(other, 'blocked_prop').value");
9026  // ... and enumerate the property.
9027  ExpectTrue("propertyIsEnumerable.call(other, 'blocked_prop')");
9028  allowed_access_type[v8::ACCESS_HAS] = false;
9029 
9030  // Access blocked element.
9031  CompileRun("other[239] = 1");
9032 
9033  ExpectUndefined("other[239]");
9034  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239')");
9035  ExpectFalse("propertyIsEnumerable.call(other, '239')");
9036 
9037  // Enable ACCESS_HAS
9038  allowed_access_type[v8::ACCESS_HAS] = true;
9039  ExpectUndefined("other[239]");
9040  // ... and now we can get the descriptor...
9041  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '239').value");
9042  // ... and enumerate the property.
9043  ExpectTrue("propertyIsEnumerable.call(other, '239')");
9044  allowed_access_type[v8::ACCESS_HAS] = false;
9045 
9046  // Access a property with JS accessor.
9047  CompileRun("other.js_accessor_p = 2");
9048 
9049  ExpectUndefined("other.js_accessor_p");
9050  ExpectUndefined(
9051  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p')");
9052 
9053  // Enable ACCESS_HAS.
9054  allowed_access_type[v8::ACCESS_HAS] = true;
9055  ExpectUndefined("other.js_accessor_p");
9056  ExpectUndefined(
9057  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9058  ExpectUndefined(
9059  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9060  ExpectUndefined(
9061  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9062  allowed_access_type[v8::ACCESS_HAS] = false;
9063 
9064  // Enable both ACCESS_HAS and ACCESS_GET.
9065  allowed_access_type[v8::ACCESS_HAS] = true;
9066  allowed_access_type[v8::ACCESS_GET] = true;
9067 
9068  ExpectString("other.js_accessor_p", "getter");
9069  ExpectObject(
9070  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9071  ExpectUndefined(
9072  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set");
9073  ExpectUndefined(
9074  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9075 
9076  allowed_access_type[v8::ACCESS_GET] = false;
9077  allowed_access_type[v8::ACCESS_HAS] = false;
9078 
9079  // Enable both ACCESS_HAS and ACCESS_SET.
9080  allowed_access_type[v8::ACCESS_HAS] = true;
9081  allowed_access_type[v8::ACCESS_SET] = true;
9082 
9083  ExpectUndefined("other.js_accessor_p");
9084  ExpectUndefined(
9085  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get");
9086  ExpectObject(
9087  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9088  ExpectUndefined(
9089  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9090 
9091  allowed_access_type[v8::ACCESS_SET] = false;
9092  allowed_access_type[v8::ACCESS_HAS] = false;
9093 
9094  // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9095  allowed_access_type[v8::ACCESS_HAS] = true;
9096  allowed_access_type[v8::ACCESS_GET] = true;
9097  allowed_access_type[v8::ACCESS_SET] = true;
9098 
9099  ExpectString("other.js_accessor_p", "getter");
9100  ExpectObject(
9101  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
9102  ExpectObject(
9103  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
9104  ExpectUndefined(
9105  "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
9106 
9107  allowed_access_type[v8::ACCESS_SET] = false;
9108  allowed_access_type[v8::ACCESS_GET] = false;
9109  allowed_access_type[v8::ACCESS_HAS] = false;
9110 
9111  // Access an element with JS accessor.
9112  CompileRun("other[42] = 2");
9113 
9114  ExpectUndefined("other[42]");
9115  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42')");
9116 
9117  // Enable ACCESS_HAS.
9118  allowed_access_type[v8::ACCESS_HAS] = true;
9119  ExpectUndefined("other[42]");
9120  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9121  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9122  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9123  allowed_access_type[v8::ACCESS_HAS] = false;
9124 
9125  // Enable both ACCESS_HAS and ACCESS_GET.
9126  allowed_access_type[v8::ACCESS_HAS] = true;
9127  allowed_access_type[v8::ACCESS_GET] = true;
9128 
9129  ExpectString("other[42]", "el_getter");
9130  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9131  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').set");
9132  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9133 
9134  allowed_access_type[v8::ACCESS_GET] = false;
9135  allowed_access_type[v8::ACCESS_HAS] = false;
9136 
9137  // Enable both ACCESS_HAS and ACCESS_SET.
9138  allowed_access_type[v8::ACCESS_HAS] = true;
9139  allowed_access_type[v8::ACCESS_SET] = true;
9140 
9141  ExpectUndefined("other[42]");
9142  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').get");
9143  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9144  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9145 
9146  allowed_access_type[v8::ACCESS_SET] = false;
9147  allowed_access_type[v8::ACCESS_HAS] = false;
9148 
9149  // Enable both ACCESS_HAS, ACCESS_GET and ACCESS_SET.
9150  allowed_access_type[v8::ACCESS_HAS] = true;
9151  allowed_access_type[v8::ACCESS_GET] = true;
9152  allowed_access_type[v8::ACCESS_SET] = true;
9153 
9154  ExpectString("other[42]", "el_getter");
9155  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
9156  ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
9157  ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
9158 
9159  allowed_access_type[v8::ACCESS_SET] = false;
9160  allowed_access_type[v8::ACCESS_GET] = false;
9161  allowed_access_type[v8::ACCESS_HAS] = false;
9162 
9163  v8::Handle<Value> value;
9164 
9165  // Access accessible property
9166  value = CompileRun("other.accessible_prop = 3");
9167  CHECK(value->IsNumber());
9168  CHECK_EQ(3, value->Int32Value());
9169  CHECK_EQ(3, g_echo_value_1);
9170 
9171  // Access accessible js property
9172  value = CompileRun("other.accessible_js_prop = 3");
9173  CHECK(value->IsNumber());
9174  CHECK_EQ(3, value->Int32Value());
9175  CHECK_EQ(3, g_echo_value_2);
9176 
9177  value = CompileRun("other.accessible_prop");
9178  CHECK(value->IsNumber());
9179  CHECK_EQ(3, value->Int32Value());
9180 
9181  value = CompileRun("other.accessible_js_prop");
9182  CHECK(value->IsNumber());
9183  CHECK_EQ(3, value->Int32Value());
9184 
9185  value = CompileRun(
9186  "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
9187  CHECK(value->IsNumber());
9188  CHECK_EQ(3, value->Int32Value());
9189 
9190  value = CompileRun(
9191  "Object.getOwnPropertyDescriptor(other, 'accessible_js_prop').get()");
9192  CHECK(value->IsNumber());
9193  CHECK_EQ(3, value->Int32Value());
9194 
9195  value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
9196  CHECK(value->IsTrue());
9197 
9198  value = CompileRun("propertyIsEnumerable.call(other, 'accessible_js_prop')");
9199  CHECK(value->IsTrue());
9200 
9201  // Enumeration doesn't enumerate accessors from inaccessible objects in
9202  // the prototype chain even if the accessors are in themselves accessible.
9203  value =
9204  CompileRun("(function(){var obj = {'__proto__':other};"
9205  "for (var p in obj)"
9206  " if (p == 'accessible_prop' ||"
9207  " p == 'accessible_js_prop' ||"
9208  " p == 'blocked_js_prop' ||"
9209  " p == 'blocked_js_prop') {"
9210  " return false;"
9211  " }"
9212  "return true;})()");
9213  CHECK(value->IsTrue());
9214 
9215  context1->Exit();
9216  context0->Exit();
9217 }
9218 
9219 
9220 TEST(AccessControlES5) {
9221  v8::Isolate* isolate = CcTest::isolate();
9222  v8::HandleScope handle_scope(isolate);
9223  v8::Handle<v8::ObjectTemplate> global_template =
9224  v8::ObjectTemplate::New(isolate);
9225 
9226  global_template->SetAccessCheckCallbacks(NamedAccessBlocker,
9227  IndexedAccessBlocker);
9228 
9229  // Add accessible accessor.
9230  global_template->SetAccessor(
9231  v8_str("accessible_prop"),
9232  EchoGetter, EchoSetter,
9235 
9236 
9237  // Add an accessor that is not accessible by cross-domain JS code.
9238  global_template->SetAccessor(v8_str("blocked_prop"),
9239  UnreachableGetter, UnreachableSetter,
9241  v8::DEFAULT);
9242 
9243  // Create an environment
9244  v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
9245  context0->Enter();
9246 
9247  v8::Handle<v8::Object> global0 = context0->Global();
9248 
9249  v8::Local<Context> context1 = Context::New(isolate);
9250  context1->Enter();
9251  v8::Handle<v8::Object> global1 = context1->Global();
9252  global1->Set(v8_str("other"), global0);
9253 
9254  // Regression test for issue 1154.
9255  ExpectTrue("Object.keys(other).indexOf('blocked_prop') == -1");
9256 
9257  ExpectUndefined("other.blocked_prop");
9258 
9259  // Regression test for issue 1027.
9260  CompileRun("Object.defineProperty(\n"
9261  " other, 'blocked_prop', {configurable: false})");
9262  ExpectUndefined("other.blocked_prop");
9263  ExpectUndefined(
9264  "Object.getOwnPropertyDescriptor(other, 'blocked_prop')");
9265 
9266  // Regression test for issue 1171.
9267  ExpectTrue("Object.isExtensible(other)");
9268  CompileRun("Object.preventExtensions(other)");
9269  ExpectTrue("Object.isExtensible(other)");
9270 
9271  // Object.seal and Object.freeze.
9272  CompileRun("Object.freeze(other)");
9273  ExpectTrue("Object.isExtensible(other)");
9274 
9275  CompileRun("Object.seal(other)");
9276  ExpectTrue("Object.isExtensible(other)");
9277 
9278  // Regression test for issue 1250.
9279  // Make sure that we can set the accessible accessors value using normal
9280  // assignment.
9281  CompileRun("other.accessible_prop = 42");
9282  CHECK_EQ(42, g_echo_value_1);
9283 
9284  v8::Handle<Value> value;
9285  // We follow Safari in ignoring assignments to host object accessors.
9286  CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
9287  value = CompileRun("other.accessible_prop == 42");
9288  CHECK(value->IsTrue());
9289 }
9290 
9291 
9292 static bool GetOwnPropertyNamesNamedBlocker(Local<v8::Object> global,
9293  Local<Value> name,
9294  v8::AccessType type,
9295  Local<Value> data) {
9296  return false;
9297 }
9298 
9299 
9300 static bool GetOwnPropertyNamesIndexedBlocker(Local<v8::Object> global,
9301  uint32_t key,
9302  v8::AccessType type,
9303  Local<Value> data) {
9304  return false;
9305 }
9306 
9307 
9308 THREADED_TEST(AccessControlGetOwnPropertyNames) {
9309  v8::Isolate* isolate = CcTest::isolate();
9310  v8::HandleScope handle_scope(isolate);
9311  v8::Handle<v8::ObjectTemplate> obj_template =
9312  v8::ObjectTemplate::New(isolate);
9313 
9314  obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9315  obj_template->SetAccessCheckCallbacks(GetOwnPropertyNamesNamedBlocker,
9316  GetOwnPropertyNamesIndexedBlocker);
9317 
9318  // Create an environment
9319  v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
9320  context0->Enter();
9321 
9322  v8::Handle<v8::Object> global0 = context0->Global();
9323 
9324  v8::HandleScope scope1(CcTest::isolate());
9325 
9326  v8::Local<Context> context1 = Context::New(isolate);
9327  context1->Enter();
9328 
9329  v8::Handle<v8::Object> global1 = context1->Global();
9330  global1->Set(v8_str("other"), global0);
9331  global1->Set(v8_str("object"), obj_template->NewInstance());
9332 
9333  v8::Handle<Value> value;
9334 
9335  // Attempt to get the property names of the other global object and
9336  // of an object that requires access checks. Accessing the other
9337  // global object should be blocked by access checks on the global
9338  // proxy object. Accessing the object that requires access checks
9339  // is blocked by the access checks on the object itself.
9340  value = CompileRun("Object.getOwnPropertyNames(other).length == 0");
9341  CHECK(value->IsTrue());
9342 
9343  value = CompileRun("Object.getOwnPropertyNames(object).length == 0");
9344  CHECK(value->IsTrue());
9345 
9346  context1->Exit();
9347  context0->Exit();
9348 }
9349 
9350 
9351 static void IndexedPropertyEnumerator(
9353  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
9354  result->Set(0, v8::Integer::New(info.GetIsolate(), 7));
9355  result->Set(1, v8::Object::New(info.GetIsolate()));
9356  info.GetReturnValue().Set(result);
9357 }
9358 
9359 
9360 static void NamedPropertyEnumerator(
9362  v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate(), 2);
9363  result->Set(0, v8_str("x"));
9364  result->Set(1, v8::Object::New(info.GetIsolate()));
9365  info.GetReturnValue().Set(result);
9366 }
9367 
9368 
9369 THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
9370  v8::Isolate* isolate = CcTest::isolate();
9371  v8::HandleScope handle_scope(isolate);
9372  v8::Handle<v8::ObjectTemplate> obj_template =
9373  v8::ObjectTemplate::New(isolate);
9374 
9375  obj_template->Set(v8_str("7"), v8::Integer::New(CcTest::isolate(), 7));
9376  obj_template->Set(v8_str("x"), v8::Integer::New(CcTest::isolate(), 42));
9377  obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
9378  IndexedPropertyEnumerator);
9379  obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
9380  NamedPropertyEnumerator);
9381 
9382  LocalContext context;
9383  v8::Handle<v8::Object> global = context->Global();
9384  global->Set(v8_str("object"), obj_template->NewInstance());
9385 
9386  v8::Handle<v8::Value> result =
9387  CompileRun("Object.getOwnPropertyNames(object)");
9388  CHECK(result->IsArray());
9389  v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
9390  CHECK_EQ(3, result_array->Length());
9391  CHECK(result_array->Get(0)->IsString());
9392  CHECK(result_array->Get(1)->IsString());
9393  CHECK(result_array->Get(2)->IsString());
9394  CHECK_EQ(v8_str("7"), result_array->Get(0));
9395  CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
9396  CHECK_EQ(v8_str("x"), result_array->Get(2));
9397 }
9398 
9399 
9400 static void ConstTenGetter(Local<String> name,
9402  info.GetReturnValue().Set(v8_num(10));
9403 }
9404 
9405 
9406 THREADED_TEST(CrossDomainAccessors) {
9407  v8::Isolate* isolate = CcTest::isolate();
9408  v8::HandleScope handle_scope(isolate);
9409 
9410  v8::Handle<v8::FunctionTemplate> func_template =
9411  v8::FunctionTemplate::New(isolate);
9412 
9413  v8::Handle<v8::ObjectTemplate> global_template =
9414  func_template->InstanceTemplate();
9415 
9416  v8::Handle<v8::ObjectTemplate> proto_template =
9417  func_template->PrototypeTemplate();
9418 
9419  // Add an accessor to proto that's accessible by cross-domain JS code.
9420  proto_template->SetAccessor(v8_str("accessible"),
9421  ConstTenGetter, 0,
9424 
9425  // Add an accessor that is not accessible by cross-domain JS code.
9426  global_template->SetAccessor(v8_str("unreachable"),
9427  UnreachableGetter, 0,
9429  v8::DEFAULT);
9430 
9431  v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
9432  context0->Enter();
9433 
9434  Local<v8::Object> global = context0->Global();
9435  // Add a normal property that shadows 'accessible'
9436  global->Set(v8_str("accessible"), v8_num(11));
9437 
9438  // Enter a new context.
9439  v8::HandleScope scope1(CcTest::isolate());
9440  v8::Local<Context> context1 = Context::New(isolate);
9441  context1->Enter();
9442 
9443  v8::Handle<v8::Object> global1 = context1->Global();
9444  global1->Set(v8_str("other"), global);
9445 
9446  // Should return 10, instead of 11
9447  v8::Handle<Value> value = v8_compile("other.accessible")->Run();
9448  CHECK(value->IsNumber());
9449  CHECK_EQ(10, value->Int32Value());
9450 
9451  value = v8_compile("other.unreachable")->Run();
9452  CHECK(value->IsUndefined());
9453 
9454  context1->Exit();
9455  context0->Exit();
9456 }
9457 
9458 
9459 static int named_access_count = 0;
9460 static int indexed_access_count = 0;
9461 
9462 static bool NamedAccessCounter(Local<v8::Object> global,
9463  Local<Value> name,
9464  v8::AccessType type,
9465  Local<Value> data) {
9466  named_access_count++;
9467  return true;
9468 }
9469 
9470 
9471 static bool IndexedAccessCounter(Local<v8::Object> global,
9472  uint32_t key,
9473  v8::AccessType type,
9474  Local<Value> data) {
9475  indexed_access_count++;
9476  return true;
9477 }
9478 
9479 
9480 // This one is too easily disturbed by other tests.
9481 TEST(AccessControlIC) {
9482  named_access_count = 0;
9483  indexed_access_count = 0;
9484 
9485  v8::Isolate* isolate = CcTest::isolate();
9486  v8::HandleScope handle_scope(isolate);
9487 
9488  // Create an environment.
9489  v8::Local<Context> context0 = Context::New(isolate);
9490  context0->Enter();
9491 
9492  // Create an object that requires access-check functions to be
9493  // called for cross-domain access.
9494  v8::Handle<v8::ObjectTemplate> object_template =
9495  v8::ObjectTemplate::New(isolate);
9496  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9497  IndexedAccessCounter);
9498  Local<v8::Object> object = object_template->NewInstance();
9499 
9500  v8::HandleScope scope1(isolate);
9501 
9502  // Create another environment.
9503  v8::Local<Context> context1 = Context::New(isolate);
9504  context1->Enter();
9505 
9506  // Make easy access to the object from the other environment.
9507  v8::Handle<v8::Object> global1 = context1->Global();
9508  global1->Set(v8_str("obj"), object);
9509 
9510  v8::Handle<Value> value;
9511 
9512  // Check that the named access-control function is called every time.
9513  CompileRun("function testProp(obj) {"
9514  " for (var i = 0; i < 10; i++) obj.prop = 1;"
9515  " for (var j = 0; j < 10; j++) obj.prop;"
9516  " return obj.prop"
9517  "}");
9518  value = CompileRun("testProp(obj)");
9519  CHECK(value->IsNumber());
9520  CHECK_EQ(1, value->Int32Value());
9521  CHECK_EQ(21, named_access_count);
9522 
9523  // Check that the named access-control function is called every time.
9524  CompileRun("var p = 'prop';"
9525  "function testKeyed(obj) {"
9526  " for (var i = 0; i < 10; i++) obj[p] = 1;"
9527  " for (var j = 0; j < 10; j++) obj[p];"
9528  " return obj[p];"
9529  "}");
9530  // Use obj which requires access checks. No inline caching is used
9531  // in that case.
9532  value = CompileRun("testKeyed(obj)");
9533  CHECK(value->IsNumber());
9534  CHECK_EQ(1, value->Int32Value());
9535  CHECK_EQ(42, named_access_count);
9536  // Force the inline caches into generic state and try again.
9537  CompileRun("testKeyed({ a: 0 })");
9538  CompileRun("testKeyed({ b: 0 })");
9539  value = CompileRun("testKeyed(obj)");
9540  CHECK(value->IsNumber());
9541  CHECK_EQ(1, value->Int32Value());
9542  CHECK_EQ(63, named_access_count);
9543 
9544  // Check that the indexed access-control function is called every time.
9545  CompileRun("function testIndexed(obj) {"
9546  " for (var i = 0; i < 10; i++) obj[0] = 1;"
9547  " for (var j = 0; j < 10; j++) obj[0];"
9548  " return obj[0]"
9549  "}");
9550  value = CompileRun("testIndexed(obj)");
9551  CHECK(value->IsNumber());
9552  CHECK_EQ(1, value->Int32Value());
9553  CHECK_EQ(21, indexed_access_count);
9554  // Force the inline caches into generic state.
9555  CompileRun("testIndexed(new Array(1))");
9556  // Test that the indexed access check is called.
9557  value = CompileRun("testIndexed(obj)");
9558  CHECK(value->IsNumber());
9559  CHECK_EQ(1, value->Int32Value());
9560  CHECK_EQ(42, indexed_access_count);
9561 
9562  // Check that the named access check is called when invoking
9563  // functions on an object that requires access checks.
9564  CompileRun("obj.f = function() {}");
9565  CompileRun("function testCallNormal(obj) {"
9566  " for (var i = 0; i < 10; i++) obj.f();"
9567  "}");
9568  CompileRun("testCallNormal(obj)");
9569  CHECK_EQ(74, named_access_count);
9570 
9571  // Force obj into slow case.
9572  value = CompileRun("delete obj.prop");
9573  CHECK(value->BooleanValue());
9574  // Force inline caches into dictionary probing mode.
9575  CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9576  // Test that the named access check is called.
9577  value = CompileRun("testProp(obj);");
9578  CHECK(value->IsNumber());
9579  CHECK_EQ(1, value->Int32Value());
9580  CHECK_EQ(96, named_access_count);
9581 
9582  // Force the call inline cache into dictionary probing mode.
9583  CompileRun("o.f = function() {}; testCallNormal(o)");
9584  // Test that the named access check is still called for each
9585  // invocation of the function.
9586  value = CompileRun("testCallNormal(obj)");
9587  CHECK_EQ(106, named_access_count);
9588 
9589  context1->Exit();
9590  context0->Exit();
9591 }
9592 
9593 
9594 static bool NamedAccessFlatten(Local<v8::Object> global,
9595  Local<Value> name,
9596  v8::AccessType type,
9597  Local<Value> data) {
9598  char buf[100];
9599  int len;
9600 
9601  CHECK(name->IsString());
9602 
9603  memset(buf, 0x1, sizeof(buf));
9604  len = name.As<String>()->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
9605  CHECK_EQ(4, len);
9606 
9607  uint16_t buf2[100];
9608 
9609  memset(buf, 0x1, sizeof(buf));
9610  len = name.As<String>()->Write(buf2);
9611  CHECK_EQ(4, len);
9612 
9613  return true;
9614 }
9615 
9616 
9617 static bool IndexedAccessFlatten(Local<v8::Object> global,
9618  uint32_t key,
9619  v8::AccessType type,
9620  Local<Value> data) {
9621  return true;
9622 }
9623 
9624 
9625 // Regression test. In access checks, operations that may cause
9626 // garbage collection are not allowed. It used to be the case that
9627 // using the Write operation on a string could cause a garbage
9628 // collection due to flattening of the string. This is no longer the
9629 // case.
9630 THREADED_TEST(AccessControlFlatten) {
9631  named_access_count = 0;
9632  indexed_access_count = 0;
9633 
9634  v8::Isolate* isolate = CcTest::isolate();
9635  v8::HandleScope handle_scope(isolate);
9636 
9637  // Create an environment.
9638  v8::Local<Context> context0 = Context::New(isolate);
9639  context0->Enter();
9640 
9641  // Create an object that requires access-check functions to be
9642  // called for cross-domain access.
9643  v8::Handle<v8::ObjectTemplate> object_template =
9644  v8::ObjectTemplate::New(isolate);
9645  object_template->SetAccessCheckCallbacks(NamedAccessFlatten,
9646  IndexedAccessFlatten);
9647  Local<v8::Object> object = object_template->NewInstance();
9648 
9649  v8::HandleScope scope1(isolate);
9650 
9651  // Create another environment.
9652  v8::Local<Context> context1 = Context::New(isolate);
9653  context1->Enter();
9654 
9655  // Make easy access to the object from the other environment.
9656  v8::Handle<v8::Object> global1 = context1->Global();
9657  global1->Set(v8_str("obj"), object);
9658 
9659  v8::Handle<Value> value;
9660 
9661  value = v8_compile("var p = 'as' + 'df';")->Run();
9662  value = v8_compile("obj[p];")->Run();
9663 
9664  context1->Exit();
9665  context0->Exit();
9666 }
9667 
9668 
9669 static void AccessControlNamedGetter(
9670  Local<String>,
9672  info.GetReturnValue().Set(42);
9673 }
9674 
9675 
9676 static void AccessControlNamedSetter(
9677  Local<String>,
9678  Local<Value> value,
9680  info.GetReturnValue().Set(value);
9681 }
9682 
9683 
9684 static void AccessControlIndexedGetter(
9685  uint32_t index,
9687  info.GetReturnValue().Set(v8_num(42));
9688 }
9689 
9690 
9691 static void AccessControlIndexedSetter(
9692  uint32_t,
9693  Local<Value> value,
9695  info.GetReturnValue().Set(value);
9696 }
9697 
9698 
9699 THREADED_TEST(AccessControlInterceptorIC) {
9700  named_access_count = 0;
9701  indexed_access_count = 0;
9702 
9703  v8::Isolate* isolate = CcTest::isolate();
9704  v8::HandleScope handle_scope(isolate);
9705 
9706  // Create an environment.
9707  v8::Local<Context> context0 = Context::New(isolate);
9708  context0->Enter();
9709 
9710  // Create an object that requires access-check functions to be
9711  // called for cross-domain access. The object also has interceptors
9712  // interceptor.
9713  v8::Handle<v8::ObjectTemplate> object_template =
9714  v8::ObjectTemplate::New(isolate);
9715  object_template->SetAccessCheckCallbacks(NamedAccessCounter,
9716  IndexedAccessCounter);
9717  object_template->SetNamedPropertyHandler(AccessControlNamedGetter,
9718  AccessControlNamedSetter);
9719  object_template->SetIndexedPropertyHandler(AccessControlIndexedGetter,
9720  AccessControlIndexedSetter);
9721  Local<v8::Object> object = object_template->NewInstance();
9722 
9723  v8::HandleScope scope1(isolate);
9724 
9725  // Create another environment.
9726  v8::Local<Context> context1 = Context::New(isolate);
9727  context1->Enter();
9728 
9729  // Make easy access to the object from the other environment.
9730  v8::Handle<v8::Object> global1 = context1->Global();
9731  global1->Set(v8_str("obj"), object);
9732 
9733  v8::Handle<Value> value;
9734 
9735  // Check that the named access-control function is called every time
9736  // eventhough there is an interceptor on the object.
9737  value = v8_compile("for (var i = 0; i < 10; i++) obj.x = 1;")->Run();
9738  value = v8_compile("for (var i = 0; i < 10; i++) obj.x;"
9739  "obj.x")->Run();
9740  CHECK(value->IsNumber());
9741  CHECK_EQ(42, value->Int32Value());
9742  CHECK_EQ(21, named_access_count);
9743 
9744  value = v8_compile("var p = 'x';")->Run();
9745  value = v8_compile("for (var i = 0; i < 10; i++) obj[p] = 1;")->Run();
9746  value = v8_compile("for (var i = 0; i < 10; i++) obj[p];"
9747  "obj[p]")->Run();
9748  CHECK(value->IsNumber());
9749  CHECK_EQ(42, value->Int32Value());
9750  CHECK_EQ(42, named_access_count);
9751 
9752  // Check that the indexed access-control function is called every
9753  // time eventhough there is an interceptor on the object.
9754  value = v8_compile("for (var i = 0; i < 10; i++) obj[0] = 1;")->Run();
9755  value = v8_compile("for (var i = 0; i < 10; i++) obj[0];"
9756  "obj[0]")->Run();
9757  CHECK(value->IsNumber());
9758  CHECK_EQ(42, value->Int32Value());
9759  CHECK_EQ(21, indexed_access_count);
9760 
9761  context1->Exit();
9762  context0->Exit();
9763 }
9764 
9765 
9768 }
9769 
9770 
9771 static void InstanceFunctionCallback(
9774  args.GetReturnValue().Set(v8_num(12));
9775 }
9776 
9777 
9778 THREADED_TEST(InstanceProperties) {
9779  LocalContext context;
9780  v8::Isolate* isolate = context->GetIsolate();
9781  v8::HandleScope handle_scope(isolate);
9782 
9783  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9784  Local<ObjectTemplate> instance = t->InstanceTemplate();
9785 
9786  instance->Set(v8_str("x"), v8_num(42));
9787  instance->Set(v8_str("f"),
9788  v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
9789 
9790  Local<Value> o = t->GetFunction()->NewInstance();
9791 
9792  context->Global()->Set(v8_str("i"), o);
9793  Local<Value> value = CompileRun("i.x");
9794  CHECK_EQ(42, value->Int32Value());
9795 
9796  value = CompileRun("i.f()");
9797  CHECK_EQ(12, value->Int32Value());
9798 }
9799 
9800 
9801 static void GlobalObjectInstancePropertiesGet(
9802  Local<String> key,
9805 }
9806 
9807 
9808 THREADED_TEST(GlobalObjectInstanceProperties) {
9809  v8::Isolate* isolate = CcTest::isolate();
9810  v8::HandleScope handle_scope(isolate);
9811 
9812  Local<Value> global_object;
9813 
9814  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9815  t->InstanceTemplate()->SetNamedPropertyHandler(
9816  GlobalObjectInstancePropertiesGet);
9817  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9818  instance_template->Set(v8_str("x"), v8_num(42));
9819  instance_template->Set(v8_str("f"),
9820  v8::FunctionTemplate::New(isolate,
9821  InstanceFunctionCallback));
9822 
9823  // The script to check how Crankshaft compiles missing global function
9824  // invocations. function g is not defined and should throw on call.
9825  const char* script =
9826  "function wrapper(call) {"
9827  " var x = 0, y = 1;"
9828  " for (var i = 0; i < 1000; i++) {"
9829  " x += i * 100;"
9830  " y += i * 100;"
9831  " }"
9832  " if (call) g();"
9833  "}"
9834  "for (var i = 0; i < 17; i++) wrapper(false);"
9835  "var thrown = 0;"
9836  "try { wrapper(true); } catch (e) { thrown = 1; };"
9837  "thrown";
9838 
9839  {
9840  LocalContext env(NULL, instance_template);
9841  // Hold on to the global object so it can be used again in another
9842  // environment initialization.
9843  global_object = env->Global();
9844 
9845  Local<Value> value = CompileRun("x");
9846  CHECK_EQ(42, value->Int32Value());
9847  value = CompileRun("f()");
9848  CHECK_EQ(12, value->Int32Value());
9849  value = CompileRun(script);
9850  CHECK_EQ(1, value->Int32Value());
9851  }
9852 
9853  {
9854  // Create new environment reusing the global object.
9855  LocalContext env(NULL, instance_template, global_object);
9856  Local<Value> value = CompileRun("x");
9857  CHECK_EQ(42, value->Int32Value());
9858  value = CompileRun("f()");
9859  CHECK_EQ(12, value->Int32Value());
9860  value = CompileRun(script);
9861  CHECK_EQ(1, value->Int32Value());
9862  }
9863 }
9864 
9865 
9866 THREADED_TEST(CallKnownGlobalReceiver) {
9867  v8::Isolate* isolate = CcTest::isolate();
9868  v8::HandleScope handle_scope(isolate);
9869 
9870  Local<Value> global_object;
9871 
9872  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9873  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9874 
9875  // The script to check that we leave global object not
9876  // global object proxy on stack when we deoptimize from inside
9877  // arguments evaluation.
9878  // To provoke error we need to both force deoptimization
9879  // from arguments evaluation and to force CallIC to take
9880  // CallIC_Miss code path that can't cope with global proxy.
9881  const char* script =
9882  "function bar(x, y) { try { } finally { } }"
9883  "function baz(x) { try { } finally { } }"
9884  "function bom(x) { try { } finally { } }"
9885  "function foo(x) { bar([x], bom(2)); }"
9886  "for (var i = 0; i < 10000; i++) foo(1);"
9887  "foo";
9888 
9889  Local<Value> foo;
9890  {
9891  LocalContext env(NULL, instance_template);
9892  // Hold on to the global object so it can be used again in another
9893  // environment initialization.
9894  global_object = env->Global();
9895  foo = CompileRun(script);
9896  }
9897 
9898  {
9899  // Create new environment reusing the global object.
9900  LocalContext env(NULL, instance_template, global_object);
9901  env->Global()->Set(v8_str("foo"), foo);
9902  CompileRun("foo()");
9903  }
9904 }
9905 
9906 
9907 static void ShadowFunctionCallback(
9910  args.GetReturnValue().Set(v8_num(42));
9911 }
9912 
9913 
9914 static int shadow_y;
9915 static int shadow_y_setter_call_count;
9916 static int shadow_y_getter_call_count;
9917 
9918 
9919 static void ShadowYSetter(Local<String>,
9920  Local<Value>,
9922  shadow_y_setter_call_count++;
9923  shadow_y = 42;
9924 }
9925 
9926 
9927 static void ShadowYGetter(Local<String> name,
9930  shadow_y_getter_call_count++;
9931  info.GetReturnValue().Set(v8_num(shadow_y));
9932 }
9933 
9934 
9935 static void ShadowIndexedGet(uint32_t index,
9937 }
9938 
9939 
9940 static void ShadowNamedGet(Local<String> key,
9942 }
9943 
9944 
9945 THREADED_TEST(ShadowObject) {
9946  shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
9947  v8::Isolate* isolate = CcTest::isolate();
9948  v8::HandleScope handle_scope(isolate);
9949 
9950  Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
9951  LocalContext context(NULL, global_template);
9952 
9953  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9954  t->InstanceTemplate()->SetNamedPropertyHandler(ShadowNamedGet);
9955  t->InstanceTemplate()->SetIndexedPropertyHandler(ShadowIndexedGet);
9956  Local<ObjectTemplate> proto = t->PrototypeTemplate();
9957  Local<ObjectTemplate> instance = t->InstanceTemplate();
9958 
9959  proto->Set(v8_str("f"),
9960  v8::FunctionTemplate::New(isolate,
9961  ShadowFunctionCallback,
9962  Local<Value>()));
9963  proto->Set(v8_str("x"), v8_num(12));
9964 
9965  instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9966 
9967  Local<Value> o = t->GetFunction()->NewInstance();
9968  context->Global()->Set(v8_str("__proto__"), o);
9969 
9970  Local<Value> value =
9971  CompileRun("this.propertyIsEnumerable(0)");
9972  CHECK(value->IsBoolean());
9973  CHECK(!value->BooleanValue());
9974 
9975  value = CompileRun("x");
9976  CHECK_EQ(12, value->Int32Value());
9977 
9978  value = CompileRun("f()");
9979  CHECK_EQ(42, value->Int32Value());
9980 
9981  CompileRun("y = 43");
9982  CHECK_EQ(1, shadow_y_setter_call_count);
9983  value = CompileRun("y");
9984  CHECK_EQ(1, shadow_y_getter_call_count);
9985  CHECK_EQ(42, value->Int32Value());
9986 }
9987 
9988 
9989 THREADED_TEST(HiddenPrototype) {
9990  LocalContext context;
9991  v8::Isolate* isolate = context->GetIsolate();
9992  v8::HandleScope handle_scope(isolate);
9993 
9994  Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9995  t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9996  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9997  t1->SetHiddenPrototype(true);
9998  t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9999  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10000  t2->SetHiddenPrototype(true);
10001  t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
10002  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
10003  t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10004 
10005  Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10006  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10007  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10008  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10009 
10010  // Setting the prototype on an object skips hidden prototypes.
10011  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10012  o0->Set(v8_str("__proto__"), o1);
10013  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10014  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10015  o0->Set(v8_str("__proto__"), o2);
10016  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10017  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10018  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10019  o0->Set(v8_str("__proto__"), o3);
10020  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10021  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10022  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10023  CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10024 
10025  // Getting the prototype of o0 should get the first visible one
10026  // which is o3. Therefore, z should not be defined on the prototype
10027  // object.
10028  Local<Value> proto = o0->Get(v8_str("__proto__"));
10029  CHECK(proto->IsObject());
10030  CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
10031 }
10032 
10033 
10034 THREADED_TEST(HiddenPrototypeSet) {
10035  LocalContext context;
10036  v8::Isolate* isolate = context->GetIsolate();
10037  v8::HandleScope handle_scope(isolate);
10038 
10039  Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
10040  Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
10041  ht->SetHiddenPrototype(true);
10042  Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
10043  ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10044 
10045  Local<v8::Object> o = ot->GetFunction()->NewInstance();
10046  Local<v8::Object> h = ht->GetFunction()->NewInstance();
10047  Local<v8::Object> p = pt->GetFunction()->NewInstance();
10048  o->Set(v8_str("__proto__"), h);
10049  h->Set(v8_str("__proto__"), p);
10050 
10051  // Setting a property that exists on the hidden prototype goes there.
10052  o->Set(v8_str("x"), v8_num(7));
10053  CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
10054  CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
10055  CHECK(p->Get(v8_str("x"))->IsUndefined());
10056 
10057  // Setting a new property should not be forwarded to the hidden prototype.
10058  o->Set(v8_str("y"), v8_num(6));
10059  CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
10060  CHECK(h->Get(v8_str("y"))->IsUndefined());
10061  CHECK(p->Get(v8_str("y"))->IsUndefined());
10062 
10063  // Setting a property that only exists on a prototype of the hidden prototype
10064  // is treated normally again.
10065  p->Set(v8_str("z"), v8_num(8));
10066  CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
10067  CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10068  CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10069  o->Set(v8_str("z"), v8_num(9));
10070  CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
10071  CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
10072  CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
10073 }
10074 
10075 
10076 // Regression test for issue 2457.
10077 THREADED_TEST(HiddenPrototypeIdentityHash) {
10078  LocalContext context;
10079  v8::HandleScope handle_scope(context->GetIsolate());
10080 
10081  Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
10082  t->SetHiddenPrototype(true);
10083  t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
10084  Handle<Object> p = t->GetFunction()->NewInstance();
10085  Handle<Object> o = Object::New(context->GetIsolate());
10086  o->SetPrototype(p);
10087 
10088  int hash = o->GetIdentityHash();
10089  USE(hash);
10090  o->Set(v8_str("foo"), v8_num(42));
10091  ASSERT_EQ(hash, o->GetIdentityHash());
10092 }
10093 
10094 
10095 THREADED_TEST(SetPrototype) {
10096  LocalContext context;
10097  v8::Isolate* isolate = context->GetIsolate();
10098  v8::HandleScope handle_scope(isolate);
10099 
10100  Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
10101  t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
10102  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10103  t1->SetHiddenPrototype(true);
10104  t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
10105  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10106  t2->SetHiddenPrototype(true);
10107  t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
10108  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
10109  t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
10110 
10111  Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
10112  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10113  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10114  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10115 
10116  // Setting the prototype on an object does not skip hidden prototypes.
10117  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10118  CHECK(o0->SetPrototype(o1));
10119  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10120  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10121  CHECK(o1->SetPrototype(o2));
10122  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10123  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10124  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10125  CHECK(o2->SetPrototype(o3));
10126  CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
10127  CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
10128  CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
10129  CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
10130 
10131  // Getting the prototype of o0 should get the first visible one
10132  // which is o3. Therefore, z should not be defined on the prototype
10133  // object.
10134  Local<Value> proto = o0->Get(v8_str("__proto__"));
10135  CHECK(proto->IsObject());
10136  CHECK_EQ(proto.As<v8::Object>(), o3);
10137 
10138  // However, Object::GetPrototype ignores hidden prototype.
10139  Local<Value> proto0 = o0->GetPrototype();
10140  CHECK(proto0->IsObject());
10141  CHECK_EQ(proto0.As<v8::Object>(), o1);
10142 
10143  Local<Value> proto1 = o1->GetPrototype();
10144  CHECK(proto1->IsObject());
10145  CHECK_EQ(proto1.As<v8::Object>(), o2);
10146 
10147  Local<Value> proto2 = o2->GetPrototype();
10148  CHECK(proto2->IsObject());
10149  CHECK_EQ(proto2.As<v8::Object>(), o3);
10150 }
10151 
10152 
10153 // Getting property names of an object with a prototype chain that
10154 // triggers dictionary elements in GetLocalPropertyNames() shouldn't
10155 // crash the runtime.
10156 THREADED_TEST(Regress91517) {
10157  i::FLAG_allow_natives_syntax = true;
10158  LocalContext context;
10159  v8::Isolate* isolate = context->GetIsolate();
10160  v8::HandleScope handle_scope(isolate);
10161 
10162  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10163  t1->SetHiddenPrototype(true);
10164  t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
10165  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10166  t2->SetHiddenPrototype(true);
10167  t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
10168  t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
10169  t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
10170  Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
10171  t3->SetHiddenPrototype(true);
10172  t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
10173  Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
10174  t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
10175 
10176  // Force dictionary-based properties.
10177  i::ScopedVector<char> name_buf(1024);
10178  for (int i = 1; i <= 1000; i++) {
10179  i::OS::SNPrintF(name_buf, "sdf%d", i);
10180  t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
10181  }
10182 
10183  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10184  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10185  Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
10186  Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
10187 
10188  // Create prototype chain of hidden prototypes.
10189  CHECK(o4->SetPrototype(o3));
10190  CHECK(o3->SetPrototype(o2));
10191  CHECK(o2->SetPrototype(o1));
10192 
10193  // Call the runtime version of GetLocalPropertyNames() on the natively
10194  // created object through JavaScript.
10195  context->Global()->Set(v8_str("obj"), o4);
10196  // PROPERTY_ATTRIBUTES_NONE = 0
10197  CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
10198 
10199  ExpectInt32("names.length", 1006);
10200  ExpectTrue("names.indexOf(\"baz\") >= 0");
10201  ExpectTrue("names.indexOf(\"boo\") >= 0");
10202  ExpectTrue("names.indexOf(\"foo\") >= 0");
10203  ExpectTrue("names.indexOf(\"fuz1\") >= 0");
10204  ExpectTrue("names.indexOf(\"fuz2\") >= 0");
10205  ExpectFalse("names[1005] == undefined");
10206 }
10207 
10208 
10209 // Getting property names of an object with a hidden and inherited
10210 // prototype should not duplicate the accessor properties inherited.
10211 THREADED_TEST(Regress269562) {
10212  i::FLAG_allow_natives_syntax = true;
10213  LocalContext context;
10214  v8::HandleScope handle_scope(context->GetIsolate());
10215 
10216  Local<v8::FunctionTemplate> t1 =
10218  t1->SetHiddenPrototype(true);
10219 
10220  Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
10221  i1->SetAccessor(v8_str("foo"),
10223  i1->SetAccessor(v8_str("bar"),
10225  i1->SetAccessor(v8_str("baz"),
10227  i1->Set(v8_str("n1"), v8_num(1));
10228  i1->Set(v8_str("n2"), v8_num(2));
10229 
10230  Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
10231  Local<v8::FunctionTemplate> t2 =
10233  t2->SetHiddenPrototype(true);
10234 
10235  // Inherit from t1 and mark prototype as hidden.
10236  t2->Inherit(t1);
10237  t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
10238 
10239  Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
10240  CHECK(o2->SetPrototype(o1));
10241 
10242  v8::Local<v8::Symbol> sym =
10243  v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
10244  o1->Set(sym, v8_num(3));
10245  o1->SetHiddenValue(
10246  v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
10247 
10248  // Call the runtime version of GetLocalPropertyNames() on
10249  // the natively created object through JavaScript.
10250  context->Global()->Set(v8_str("obj"), o2);
10251  context->Global()->Set(v8_str("sym"), sym);
10252  // PROPERTY_ATTRIBUTES_NONE = 0
10253  CompileRun("var names = %GetLocalPropertyNames(obj, 0);");
10254 
10255  ExpectInt32("names.length", 7);
10256  ExpectTrue("names.indexOf(\"foo\") >= 0");
10257  ExpectTrue("names.indexOf(\"bar\") >= 0");
10258  ExpectTrue("names.indexOf(\"baz\") >= 0");
10259  ExpectTrue("names.indexOf(\"n1\") >= 0");
10260  ExpectTrue("names.indexOf(\"n2\") >= 0");
10261  ExpectTrue("names.indexOf(sym) >= 0");
10262  ExpectTrue("names.indexOf(\"mine\") >= 0");
10263 }
10264 
10265 
10266 THREADED_TEST(FunctionReadOnlyPrototype) {
10267  LocalContext context;
10268  v8::Isolate* isolate = context->GetIsolate();
10269  v8::HandleScope handle_scope(isolate);
10270 
10271  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10272  t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
10273  t1->ReadOnlyPrototype();
10274  context->Global()->Set(v8_str("func1"), t1->GetFunction());
10275  // Configured value of ReadOnly flag.
10276  CHECK(CompileRun(
10277  "(function() {"
10278  " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
10279  " return (descriptor['writable'] == false);"
10280  "})()")->BooleanValue());
10281  CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
10282  CHECK_EQ(42,
10283  CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
10284 
10285  Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
10286  t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
10287  context->Global()->Set(v8_str("func2"), t2->GetFunction());
10288  // Default value of ReadOnly flag.
10289  CHECK(CompileRun(
10290  "(function() {"
10291  " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
10292  " return (descriptor['writable'] == true);"
10293  "})()")->BooleanValue());
10294  CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
10295 }
10296 
10297 
10298 THREADED_TEST(SetPrototypeThrows) {
10299  LocalContext context;
10300  v8::Isolate* isolate = context->GetIsolate();
10301  v8::HandleScope handle_scope(isolate);
10302 
10303  Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10304 
10305  Local<v8::Object> o0 = t->GetFunction()->NewInstance();
10306  Local<v8::Object> o1 = t->GetFunction()->NewInstance();
10307 
10308  CHECK(o0->SetPrototype(o1));
10309  // If setting the prototype leads to the cycle, SetPrototype should
10310  // return false and keep VM in sane state.
10311  v8::TryCatch try_catch;
10312  CHECK(!o1->SetPrototype(o0));
10313  CHECK(!try_catch.HasCaught());
10314  ASSERT(!CcTest::i_isolate()->has_pending_exception());
10315 
10316  CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
10317 }
10318 
10319 
10320 THREADED_TEST(FunctionRemovePrototype) {
10321  LocalContext context;
10322  v8::Isolate* isolate = context->GetIsolate();
10323  v8::HandleScope handle_scope(isolate);
10324 
10325  Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
10326  t1->RemovePrototype();
10327  Local<v8::Function> fun = t1->GetFunction();
10328  context->Global()->Set(v8_str("fun"), fun);
10329  CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
10330 
10331  v8::TryCatch try_catch;
10332  CompileRun("new fun()");
10333  CHECK(try_catch.HasCaught());
10334 
10335  try_catch.Reset();
10336  fun->NewInstance();
10337  CHECK(try_catch.HasCaught());
10338 }
10339 
10340 
10341 THREADED_TEST(GetterSetterExceptions) {
10342  LocalContext context;
10343  v8::Isolate* isolate = context->GetIsolate();
10344  v8::HandleScope handle_scope(isolate);
10345  CompileRun(
10346  "function Foo() { };"
10347  "function Throw() { throw 5; };"
10348  "var x = { };"
10349  "x.__defineSetter__('set', Throw);"
10350  "x.__defineGetter__('get', Throw);");
10351  Local<v8::Object> x =
10352  Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
10353  v8::TryCatch try_catch;
10354  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10355  x->Get(v8_str("get"));
10356  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10357  x->Get(v8_str("get"));
10358  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10359  x->Get(v8_str("get"));
10360  x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
10361  x->Get(v8_str("get"));
10362 }
10363 
10364 
10365 THREADED_TEST(Constructor) {
10366  LocalContext context;
10367  v8::Isolate* isolate = context->GetIsolate();
10368  v8::HandleScope handle_scope(isolate);
10369  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
10370  templ->SetClassName(v8_str("Fun"));
10371  Local<Function> cons = templ->GetFunction();
10372  context->Global()->Set(v8_str("Fun"), cons);
10373  Local<v8::Object> inst = cons->NewInstance();
10375  CHECK(obj->IsJSObject());
10376  Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
10377  CHECK(value->BooleanValue());
10378 }
10379 
10380 
10381 static void ConstructorCallback(
10384  Local<Object> This;
10385 
10386  if (args.IsConstructCall()) {
10387  Local<Object> Holder = args.Holder();
10388  This = Object::New(args.GetIsolate());
10389  Local<Value> proto = Holder->GetPrototype();
10390  if (proto->IsObject()) {
10391  This->SetPrototype(proto);
10392  }
10393  } else {
10394  This = args.This();
10395  }
10396 
10397  This->Set(v8_str("a"), args[0]);
10398  args.GetReturnValue().Set(This);
10399 }
10400 
10401 
10402 static void FakeConstructorCallback(
10405  args.GetReturnValue().Set(args[0]);
10406 }
10407 
10408 
10409 THREADED_TEST(ConstructorForObject) {
10410  LocalContext context;
10411  v8::Isolate* isolate = context->GetIsolate();
10412  v8::HandleScope handle_scope(isolate);
10413 
10414  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10415  instance_template->SetCallAsFunctionHandler(ConstructorCallback);
10416  Local<Object> instance = instance_template->NewInstance();
10417  context->Global()->Set(v8_str("obj"), instance);
10418  v8::TryCatch try_catch;
10419  Local<Value> value;
10420  CHECK(!try_catch.HasCaught());
10421 
10422  // Call the Object's constructor with a 32-bit signed integer.
10423  value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
10424  CHECK(!try_catch.HasCaught());
10425  CHECK(value->IsInt32());
10426  CHECK_EQ(28, value->Int32Value());
10427 
10428  Local<Value> args1[] = { v8_num(28) };
10429  Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
10430  CHECK(value_obj1->IsObject());
10431  Local<Object> object1 = Local<Object>::Cast(value_obj1);
10432  value = object1->Get(v8_str("a"));
10433  CHECK(value->IsInt32());
10434  CHECK(!try_catch.HasCaught());
10435  CHECK_EQ(28, value->Int32Value());
10436 
10437  // Call the Object's constructor with a String.
10438  value = CompileRun(
10439  "(function() { var o = new obj('tipli'); return o.a; })()");
10440  CHECK(!try_catch.HasCaught());
10441  CHECK(value->IsString());
10442  String::Utf8Value string_value1(value->ToString());
10443  CHECK_EQ("tipli", *string_value1);
10444 
10445  Local<Value> args2[] = { v8_str("tipli") };
10446  Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
10447  CHECK(value_obj2->IsObject());
10448  Local<Object> object2 = Local<Object>::Cast(value_obj2);
10449  value = object2->Get(v8_str("a"));
10450  CHECK(!try_catch.HasCaught());
10451  CHECK(value->IsString());
10452  String::Utf8Value string_value2(value->ToString());
10453  CHECK_EQ("tipli", *string_value2);
10454 
10455  // Call the Object's constructor with a Boolean.
10456  value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
10457  CHECK(!try_catch.HasCaught());
10458  CHECK(value->IsBoolean());
10459  CHECK_EQ(true, value->BooleanValue());
10460 
10461  Handle<Value> args3[] = { v8::True(isolate) };
10462  Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
10463  CHECK(value_obj3->IsObject());
10464  Local<Object> object3 = Local<Object>::Cast(value_obj3);
10465  value = object3->Get(v8_str("a"));
10466  CHECK(!try_catch.HasCaught());
10467  CHECK(value->IsBoolean());
10468  CHECK_EQ(true, value->BooleanValue());
10469 
10470  // Call the Object's constructor with undefined.
10471  Handle<Value> args4[] = { v8::Undefined(isolate) };
10472  Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
10473  CHECK(value_obj4->IsObject());
10474  Local<Object> object4 = Local<Object>::Cast(value_obj4);
10475  value = object4->Get(v8_str("a"));
10476  CHECK(!try_catch.HasCaught());
10477  CHECK(value->IsUndefined());
10478 
10479  // Call the Object's constructor with null.
10480  Handle<Value> args5[] = { v8::Null(isolate) };
10481  Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
10482  CHECK(value_obj5->IsObject());
10483  Local<Object> object5 = Local<Object>::Cast(value_obj5);
10484  value = object5->Get(v8_str("a"));
10485  CHECK(!try_catch.HasCaught());
10486  CHECK(value->IsNull());
10487  }
10488 
10489  // Check exception handling when there is no constructor set for the Object.
10490  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10491  Local<Object> instance = instance_template->NewInstance();
10492  context->Global()->Set(v8_str("obj2"), instance);
10493  v8::TryCatch try_catch;
10494  Local<Value> value;
10495  CHECK(!try_catch.HasCaught());
10496 
10497  value = CompileRun("new obj2(28)");
10498  CHECK(try_catch.HasCaught());
10499  String::Utf8Value exception_value1(try_catch.Exception());
10500  CHECK_EQ("TypeError: object is not a function", *exception_value1);
10501  try_catch.Reset();
10502 
10503  Local<Value> args[] = { v8_num(29) };
10504  value = instance->CallAsConstructor(1, args);
10505  CHECK(try_catch.HasCaught());
10506  String::Utf8Value exception_value2(try_catch.Exception());
10507  CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2);
10508  try_catch.Reset();
10509  }
10510 
10511  // Check the case when constructor throws exception.
10512  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10513  instance_template->SetCallAsFunctionHandler(ThrowValue);
10514  Local<Object> instance = instance_template->NewInstance();
10515  context->Global()->Set(v8_str("obj3"), instance);
10516  v8::TryCatch try_catch;
10517  Local<Value> value;
10518  CHECK(!try_catch.HasCaught());
10519 
10520  value = CompileRun("new obj3(22)");
10521  CHECK(try_catch.HasCaught());
10522  String::Utf8Value exception_value1(try_catch.Exception());
10523  CHECK_EQ("22", *exception_value1);
10524  try_catch.Reset();
10525 
10526  Local<Value> args[] = { v8_num(23) };
10527  value = instance->CallAsConstructor(1, args);
10528  CHECK(try_catch.HasCaught());
10529  String::Utf8Value exception_value2(try_catch.Exception());
10530  CHECK_EQ("23", *exception_value2);
10531  try_catch.Reset();
10532  }
10533 
10534  // Check whether constructor returns with an object or non-object.
10535  { Local<FunctionTemplate> function_template =
10536  FunctionTemplate::New(isolate, FakeConstructorCallback);
10537  Local<Function> function = function_template->GetFunction();
10538  Local<Object> instance1 = function;
10539  context->Global()->Set(v8_str("obj4"), instance1);
10540  v8::TryCatch try_catch;
10541  Local<Value> value;
10542  CHECK(!try_catch.HasCaught());
10543 
10544  CHECK(instance1->IsObject());
10545  CHECK(instance1->IsFunction());
10546 
10547  value = CompileRun("new obj4(28)");
10548  CHECK(!try_catch.HasCaught());
10549  CHECK(value->IsObject());
10550 
10551  Local<Value> args1[] = { v8_num(28) };
10552  value = instance1->CallAsConstructor(1, args1);
10553  CHECK(!try_catch.HasCaught());
10554  CHECK(value->IsObject());
10555 
10556  Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10557  instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
10558  Local<Object> instance2 = instance_template->NewInstance();
10559  context->Global()->Set(v8_str("obj5"), instance2);
10560  CHECK(!try_catch.HasCaught());
10561 
10562  CHECK(instance2->IsObject());
10563  CHECK(!instance2->IsFunction());
10564 
10565  value = CompileRun("new obj5(28)");
10566  CHECK(!try_catch.HasCaught());
10567  CHECK(!value->IsObject());
10568 
10569  Local<Value> args2[] = { v8_num(28) };
10570  value = instance2->CallAsConstructor(1, args2);
10571  CHECK(!try_catch.HasCaught());
10572  CHECK(!value->IsObject());
10573  }
10574 }
10575 
10576 
10577 THREADED_TEST(FunctionDescriptorException) {
10578  LocalContext context;
10579  v8::Isolate* isolate = context->GetIsolate();
10580  v8::HandleScope handle_scope(isolate);
10581  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
10582  templ->SetClassName(v8_str("Fun"));
10583  Local<Function> cons = templ->GetFunction();
10584  context->Global()->Set(v8_str("Fun"), cons);
10585  Local<Value> value = CompileRun(
10586  "function test() {"
10587  " try {"
10588  " (new Fun()).blah()"
10589  " } catch (e) {"
10590  " var str = String(e);"
10591  // " if (str.indexOf('TypeError') == -1) return 1;"
10592  // " if (str.indexOf('[object Fun]') != -1) return 2;"
10593  // " if (str.indexOf('#<Fun>') == -1) return 3;"
10594  " return 0;"
10595  " }"
10596  " return 4;"
10597  "}"
10598  "test();");
10599  CHECK_EQ(0, value->Int32Value());
10600 }
10601 
10602 
10603 THREADED_TEST(EvalAliasedDynamic) {
10604  LocalContext current;
10605  v8::HandleScope scope(current->GetIsolate());
10606 
10607  // Tests where aliased eval can only be resolved dynamically.
10608  Local<Script> script = v8_compile(
10609  "function f(x) { "
10610  " var foo = 2;"
10611  " with (x) { return eval('foo'); }"
10612  "}"
10613  "foo = 0;"
10614  "result1 = f(new Object());"
10615  "result2 = f(this);"
10616  "var x = new Object();"
10617  "x.eval = function(x) { return 1; };"
10618  "result3 = f(x);");
10619  script->Run();
10620  CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
10621  CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
10622  CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
10623 
10624  v8::TryCatch try_catch;
10625  script = v8_compile(
10626  "function f(x) { "
10627  " var bar = 2;"
10628  " with (x) { return eval('bar'); }"
10629  "}"
10630  "result4 = f(this)");
10631  script->Run();
10632  CHECK(!try_catch.HasCaught());
10633  CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
10634 
10635  try_catch.Reset();
10636 }
10637 
10638 
10639 THREADED_TEST(CrossEval) {
10641  LocalContext other;
10642  LocalContext current;
10643 
10644  Local<String> token = v8_str("<security token>");
10645  other->SetSecurityToken(token);
10646  current->SetSecurityToken(token);
10647 
10648  // Set up reference from current to other.
10649  current->Global()->Set(v8_str("other"), other->Global());
10650 
10651  // Check that new variables are introduced in other context.
10652  Local<Script> script = v8_compile("other.eval('var foo = 1234')");
10653  script->Run();
10654  Local<Value> foo = other->Global()->Get(v8_str("foo"));
10655  CHECK_EQ(1234, foo->Int32Value());
10656  CHECK(!current->Global()->Has(v8_str("foo")));
10657 
10658  // Check that writing to non-existing properties introduces them in
10659  // the other context.
10660  script = v8_compile("other.eval('na = 1234')");
10661  script->Run();
10662  CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
10663  CHECK(!current->Global()->Has(v8_str("na")));
10664 
10665  // Check that global variables in current context are not visible in other
10666  // context.
10667  v8::TryCatch try_catch;
10668  script = v8_compile("var bar = 42; other.eval('bar');");
10669  Local<Value> result = script->Run();
10670  CHECK(try_catch.HasCaught());
10671  try_catch.Reset();
10672 
10673  // Check that local variables in current context are not visible in other
10674  // context.
10675  script = v8_compile(
10676  "(function() { "
10677  " var baz = 87;"
10678  " return other.eval('baz');"
10679  "})();");
10680  result = script->Run();
10681  CHECK(try_catch.HasCaught());
10682  try_catch.Reset();
10683 
10684  // Check that global variables in the other environment are visible
10685  // when evaluting code.
10686  other->Global()->Set(v8_str("bis"), v8_num(1234));
10687  script = v8_compile("other.eval('bis')");
10688  CHECK_EQ(1234, script->Run()->Int32Value());
10689  CHECK(!try_catch.HasCaught());
10690 
10691  // Check that the 'this' pointer points to the global object evaluating
10692  // code.
10693  other->Global()->Set(v8_str("t"), other->Global());
10694  script = v8_compile("other.eval('this == t')");
10695  result = script->Run();
10696  CHECK(result->IsTrue());
10697  CHECK(!try_catch.HasCaught());
10698 
10699  // Check that variables introduced in with-statement are not visible in
10700  // other context.
10701  script = v8_compile("with({x:2}){other.eval('x')}");
10702  result = script->Run();
10703  CHECK(try_catch.HasCaught());
10704  try_catch.Reset();
10705 
10706  // Check that you cannot use 'eval.call' with another object than the
10707  // current global object.
10708  script = v8_compile("other.y = 1; eval.call(other, 'y')");
10709  result = script->Run();
10710  CHECK(try_catch.HasCaught());
10711 }
10712 
10713 
10714 // Test that calling eval in a context which has been detached from
10715 // its global throws an exception. This behavior is consistent with
10716 // other JavaScript implementations.
10717 THREADED_TEST(EvalInDetachedGlobal) {
10718  v8::Isolate* isolate = CcTest::isolate();
10719  v8::HandleScope scope(isolate);
10720 
10721  v8::Local<Context> context0 = Context::New(isolate);
10722  v8::Local<Context> context1 = Context::New(isolate);
10723 
10724  // Set up function in context0 that uses eval from context0.
10725  context0->Enter();
10726  v8::Handle<v8::Value> fun =
10727  CompileRun("var x = 42;"
10728  "(function() {"
10729  " var e = eval;"
10730  " return function(s) { return e(s); }"
10731  "})()");
10732  context0->Exit();
10733 
10734  // Put the function into context1 and call it before and after
10735  // detaching the global. Before detaching, the call succeeds and
10736  // after detaching and exception is thrown.
10737  context1->Enter();
10738  context1->Global()->Set(v8_str("fun"), fun);
10739  v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10740  CHECK_EQ(42, x_value->Int32Value());
10741  context0->DetachGlobal();
10742  v8::TryCatch catcher;
10743  x_value = CompileRun("fun('x')");
10744  CHECK(x_value.IsEmpty());
10745  CHECK(catcher.HasCaught());
10746  context1->Exit();
10747 }
10748 
10749 
10750 THREADED_TEST(CrossLazyLoad) {
10752  LocalContext other;
10753  LocalContext current;
10754 
10755  Local<String> token = v8_str("<security token>");
10756  other->SetSecurityToken(token);
10757  current->SetSecurityToken(token);
10758 
10759  // Set up reference from current to other.
10760  current->Global()->Set(v8_str("other"), other->Global());
10761 
10762  // Trigger lazy loading in other context.
10763  Local<Script> script = v8_compile("other.eval('new Date(42)')");
10764  Local<Value> value = script->Run();
10765  CHECK_EQ(42.0, value->NumberValue());
10766 }
10767 
10768 
10769 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
10771  if (args.IsConstructCall()) {
10772  if (args[0]->IsInt32()) {
10773  args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10774  return;
10775  }
10776  }
10777 
10778  args.GetReturnValue().Set(args[0]);
10779 }
10780 
10781 
10782 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10783  args.GetReturnValue().Set(args.This());
10784 }
10785 
10786 
10787 // Test that a call handler can be set for objects which will allow
10788 // non-function objects created through the API to be called as
10789 // functions.
10790 THREADED_TEST(CallAsFunction) {
10791  LocalContext context;
10792  v8::Isolate* isolate = context->GetIsolate();
10793  v8::HandleScope scope(isolate);
10794 
10795  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10796  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10797  instance_template->SetCallAsFunctionHandler(call_as_function);
10798  Local<v8::Object> instance = t->GetFunction()->NewInstance();
10799  context->Global()->Set(v8_str("obj"), instance);
10800  v8::TryCatch try_catch;
10801  Local<Value> value;
10802  CHECK(!try_catch.HasCaught());
10803 
10804  value = CompileRun("obj(42)");
10805  CHECK(!try_catch.HasCaught());
10806  CHECK_EQ(42, value->Int32Value());
10807 
10808  value = CompileRun("(function(o){return o(49)})(obj)");
10809  CHECK(!try_catch.HasCaught());
10810  CHECK_EQ(49, value->Int32Value());
10811 
10812  // test special case of call as function
10813  value = CompileRun("[obj]['0'](45)");
10814  CHECK(!try_catch.HasCaught());
10815  CHECK_EQ(45, value->Int32Value());
10816 
10817  value = CompileRun("obj.call = Function.prototype.call;"
10818  "obj.call(null, 87)");
10819  CHECK(!try_catch.HasCaught());
10820  CHECK_EQ(87, value->Int32Value());
10821 
10822  // Regression tests for bug #1116356: Calling call through call/apply
10823  // must work for non-function receivers.
10824  const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10825  value = CompileRun(apply_99);
10826  CHECK(!try_catch.HasCaught());
10827  CHECK_EQ(99, value->Int32Value());
10828 
10829  const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10830  value = CompileRun(call_17);
10831  CHECK(!try_catch.HasCaught());
10832  CHECK_EQ(17, value->Int32Value());
10833 
10834  // Check that the call-as-function handler can be called through
10835  // new.
10836  value = CompileRun("new obj(43)");
10837  CHECK(!try_catch.HasCaught());
10838  CHECK_EQ(-43, value->Int32Value());
10839 
10840  // Check that the call-as-function handler can be called through
10841  // the API.
10842  v8::Handle<Value> args[] = { v8_num(28) };
10843  value = instance->CallAsFunction(instance, 1, args);
10844  CHECK(!try_catch.HasCaught());
10845  CHECK_EQ(28, value->Int32Value());
10846  }
10847 
10848  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10849  Local<ObjectTemplate> instance_template(t->InstanceTemplate());
10850  USE(instance_template);
10851  Local<v8::Object> instance = t->GetFunction()->NewInstance();
10852  context->Global()->Set(v8_str("obj2"), instance);
10853  v8::TryCatch try_catch;
10854  Local<Value> value;
10855  CHECK(!try_catch.HasCaught());
10856 
10857  // Call an object without call-as-function handler through the JS
10858  value = CompileRun("obj2(28)");
10859  CHECK(value.IsEmpty());
10860  CHECK(try_catch.HasCaught());
10861  String::Utf8Value exception_value1(try_catch.Exception());
10862  // TODO(verwaest): Better message
10863  CHECK_EQ("TypeError: object is not a function",
10864  *exception_value1);
10865  try_catch.Reset();
10866 
10867  // Call an object without call-as-function handler through the API
10868  value = CompileRun("obj2(28)");
10869  v8::Handle<Value> args[] = { v8_num(28) };
10870  value = instance->CallAsFunction(instance, 1, args);
10871  CHECK(value.IsEmpty());
10872  CHECK(try_catch.HasCaught());
10873  String::Utf8Value exception_value2(try_catch.Exception());
10874  CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2);
10875  try_catch.Reset();
10876  }
10877 
10878  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10879  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10880  instance_template->SetCallAsFunctionHandler(ThrowValue);
10881  Local<v8::Object> instance = t->GetFunction()->NewInstance();
10882  context->Global()->Set(v8_str("obj3"), instance);
10883  v8::TryCatch try_catch;
10884  Local<Value> value;
10885  CHECK(!try_catch.HasCaught());
10886 
10887  // Catch the exception which is thrown by call-as-function handler
10888  value = CompileRun("obj3(22)");
10889  CHECK(try_catch.HasCaught());
10890  String::Utf8Value exception_value1(try_catch.Exception());
10891  CHECK_EQ("22", *exception_value1);
10892  try_catch.Reset();
10893 
10894  v8::Handle<Value> args[] = { v8_num(23) };
10895  value = instance->CallAsFunction(instance, 1, args);
10896  CHECK(try_catch.HasCaught());
10897  String::Utf8Value exception_value2(try_catch.Exception());
10898  CHECK_EQ("23", *exception_value2);
10899  try_catch.Reset();
10900  }
10901 
10902  { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10903  Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10904  instance_template->SetCallAsFunctionHandler(ReturnThis);
10905  Local<v8::Object> instance = t->GetFunction()->NewInstance();
10906 
10907  Local<v8::Value> a1 =
10908  instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10909  CHECK(a1->StrictEquals(instance));
10910  Local<v8::Value> a2 =
10911  instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10912  CHECK(a2->StrictEquals(instance));
10913  Local<v8::Value> a3 =
10914  instance->CallAsFunction(v8_num(42), 0, NULL);
10915  CHECK(a3->StrictEquals(instance));
10916  Local<v8::Value> a4 =
10917  instance->CallAsFunction(v8_str("hello"), 0, NULL);
10918  CHECK(a4->StrictEquals(instance));
10919  Local<v8::Value> a5 =
10920  instance->CallAsFunction(v8::True(isolate), 0, NULL);
10921  CHECK(a5->StrictEquals(instance));
10922  }
10923 
10924  { CompileRun(
10925  "function ReturnThisSloppy() {"
10926  " return this;"
10927  "}"
10928  "function ReturnThisStrict() {"
10929  " 'use strict';"
10930  " return this;"
10931  "}");
10932  Local<Function> ReturnThisSloppy =
10933  Local<Function>::Cast(
10934  context->Global()->Get(v8_str("ReturnThisSloppy")));
10935  Local<Function> ReturnThisStrict =
10936  Local<Function>::Cast(
10937  context->Global()->Get(v8_str("ReturnThisStrict")));
10938 
10939  Local<v8::Value> a1 =
10940  ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10941  CHECK(a1->StrictEquals(context->Global()));
10942  Local<v8::Value> a2 =
10943  ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10944  CHECK(a2->StrictEquals(context->Global()));
10945  Local<v8::Value> a3 =
10946  ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10947  CHECK(a3->IsNumberObject());
10948  CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10949  Local<v8::Value> a4 =
10950  ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10951  CHECK(a4->IsStringObject());
10952  CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10953  Local<v8::Value> a5 =
10954  ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10955  CHECK(a5->IsBooleanObject());
10956  CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10957 
10958  Local<v8::Value> a6 =
10959  ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10960  CHECK(a6->IsUndefined());
10961  Local<v8::Value> a7 =
10962  ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10963  CHECK(a7->IsNull());
10964  Local<v8::Value> a8 =
10965  ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10966  CHECK(a8->StrictEquals(v8_num(42)));
10967  Local<v8::Value> a9 =
10968  ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10969  CHECK(a9->StrictEquals(v8_str("hello")));
10970  Local<v8::Value> a10 =
10971  ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10972  CHECK(a10->StrictEquals(v8::True(isolate)));
10973  }
10974 }
10975 
10976 
10977 // Check whether a non-function object is callable.
10978 THREADED_TEST(CallableObject) {
10979  LocalContext context;
10980  v8::Isolate* isolate = context->GetIsolate();
10981  v8::HandleScope scope(isolate);
10982 
10983  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10984  instance_template->SetCallAsFunctionHandler(call_as_function);
10985  Local<Object> instance = instance_template->NewInstance();
10986  v8::TryCatch try_catch;
10987 
10988  CHECK(instance->IsCallable());
10989  CHECK(!try_catch.HasCaught());
10990  }
10991 
10992  { Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10993  Local<Object> instance = instance_template->NewInstance();
10994  v8::TryCatch try_catch;
10995 
10996  CHECK(!instance->IsCallable());
10997  CHECK(!try_catch.HasCaught());
10998  }
10999 
11000  { Local<FunctionTemplate> function_template =
11001  FunctionTemplate::New(isolate, call_as_function);
11002  Local<Function> function = function_template->GetFunction();
11003  Local<Object> instance = function;
11004  v8::TryCatch try_catch;
11005 
11006  CHECK(instance->IsCallable());
11007  CHECK(!try_catch.HasCaught());
11008  }
11009 
11010  { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
11011  Local<Function> function = function_template->GetFunction();
11012  Local<Object> instance = function;
11013  v8::TryCatch try_catch;
11014 
11015  CHECK(instance->IsCallable());
11016  CHECK(!try_catch.HasCaught());
11017  }
11018 }
11019 
11020 
11021 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
11022  v8::HandleScope scope(isolate);
11023  if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
11024  for (int i = 0; i < iterations; i++) {
11025  Local<v8::Number> n(v8::Integer::New(isolate, 42));
11026  }
11027  return Recurse(isolate, depth - 1, iterations);
11028 }
11029 
11030 
11031 THREADED_TEST(HandleIteration) {
11032  static const int kIterations = 500;
11033  static const int kNesting = 200;
11034  LocalContext context;
11035  v8::Isolate* isolate = context->GetIsolate();
11036  v8::HandleScope scope0(isolate);
11038  {
11039  v8::HandleScope scope1(isolate);
11041  for (int i = 0; i < kIterations; i++) {
11042  Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
11043  CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
11044  }
11045 
11046  CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
11047  {
11048  v8::HandleScope scope2(CcTest::isolate());
11049  for (int j = 0; j < kIterations; j++) {
11050  Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
11051  CHECK_EQ(j + 1 + kIterations,
11053  }
11054  }
11055  CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
11056  }
11058  CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
11059 }
11060 
11061 
11062 static void InterceptorHasOwnPropertyGetter(
11063  Local<String> name,
11066 }
11067 
11068 
11069 THREADED_TEST(InterceptorHasOwnProperty) {
11070  LocalContext context;
11071  v8::Isolate* isolate = context->GetIsolate();
11072  v8::HandleScope scope(isolate);
11073  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
11074  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11075  instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetter);
11076  Local<Function> function = fun_templ->GetFunction();
11077  context->Global()->Set(v8_str("constructor"), function);
11078  v8::Handle<Value> value = CompileRun(
11079  "var o = new constructor();"
11080  "o.hasOwnProperty('ostehaps');");
11081  CHECK_EQ(false, value->BooleanValue());
11082  value = CompileRun(
11083  "o.ostehaps = 42;"
11084  "o.hasOwnProperty('ostehaps');");
11085  CHECK_EQ(true, value->BooleanValue());
11086  value = CompileRun(
11087  "var p = new constructor();"
11088  "p.hasOwnProperty('ostehaps');");
11089  CHECK_EQ(false, value->BooleanValue());
11090 }
11091 
11092 
11093 static void InterceptorHasOwnPropertyGetterGC(
11094  Local<String> name,
11098 }
11099 
11100 
11101 THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
11102  LocalContext context;
11103  v8::Isolate* isolate = context->GetIsolate();
11104  v8::HandleScope scope(isolate);
11105  Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
11106  Local<v8::ObjectTemplate> instance_templ = fun_templ->InstanceTemplate();
11107  instance_templ->SetNamedPropertyHandler(InterceptorHasOwnPropertyGetterGC);
11108  Local<Function> function = fun_templ->GetFunction();
11109  context->Global()->Set(v8_str("constructor"), function);
11110  // Let's first make some stuff so we can be sure to get a good GC.
11111  CompileRun(
11112  "function makestr(size) {"
11113  " switch (size) {"
11114  " case 1: return 'f';"
11115  " case 2: return 'fo';"
11116  " case 3: return 'foo';"
11117  " }"
11118  " return makestr(size >> 1) + makestr((size + 1) >> 1);"
11119  "}"
11120  "var x = makestr(12345);"
11121  "x = makestr(31415);"
11122  "x = makestr(23456);");
11123  v8::Handle<Value> value = CompileRun(
11124  "var o = new constructor();"
11125  "o.__proto__ = new String(x);"
11126  "o.hasOwnProperty('ostehaps');");
11127  CHECK_EQ(false, value->BooleanValue());
11128 }
11129 
11130 
11131 typedef void (*NamedPropertyGetter)(
11132  Local<String> property,
11134 
11135 
11136 static void CheckInterceptorLoadIC(NamedPropertyGetter getter,
11137  const char* source,
11138  int expected) {
11139  v8::Isolate* isolate = CcTest::isolate();
11140  v8::HandleScope scope(isolate);
11141  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11142  templ->SetNamedPropertyHandler(getter, 0, 0, 0, 0, v8_str("data"));
11143  LocalContext context;
11144  context->Global()->Set(v8_str("o"), templ->NewInstance());
11145  v8::Handle<Value> value = CompileRun(source);
11146  CHECK_EQ(expected, value->Int32Value());
11147 }
11148 
11149 
11150 static void InterceptorLoadICGetter(
11151  Local<String> name,
11154  v8::Isolate* isolate = CcTest::isolate();
11155  CHECK_EQ(isolate, info.GetIsolate());
11156  CHECK_EQ(v8_str("data"), info.Data());
11157  CHECK_EQ(v8_str("x"), name);
11158  info.GetReturnValue().Set(v8::Integer::New(isolate, 42));
11159 }
11160 
11161 
11162 // This test should hit the load IC for the interceptor case.
11163 THREADED_TEST(InterceptorLoadIC) {
11164  CheckInterceptorLoadIC(InterceptorLoadICGetter,
11165  "var result = 0;"
11166  "for (var i = 0; i < 1000; i++) {"
11167  " result = o.x;"
11168  "}",
11169  42);
11170 }
11171 
11172 
11173 // Below go several tests which verify that JITing for various
11174 // configurations of interceptor and explicit fields works fine
11175 // (those cases are special cased to get better performance).
11176 
11177 static void InterceptorLoadXICGetter(
11178  Local<String> name,
11181  info.GetReturnValue().Set(
11182  v8_str("x")->Equals(name) ?
11185 }
11186 
11187 
11188 THREADED_TEST(InterceptorLoadICWithFieldOnHolder) {
11189  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11190  "var result = 0;"
11191  "o.y = 239;"
11192  "for (var i = 0; i < 1000; i++) {"
11193  " result = o.y;"
11194  "}",
11195  239);
11196 }
11197 
11198 
11199 THREADED_TEST(InterceptorLoadICWithSubstitutedProto) {
11200  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11201  "var result = 0;"
11202  "o.__proto__ = { 'y': 239 };"
11203  "for (var i = 0; i < 1000; i++) {"
11204  " result = o.y + o.x;"
11205  "}",
11206  239 + 42);
11207 }
11208 
11209 
11210 THREADED_TEST(InterceptorLoadICWithPropertyOnProto) {
11211  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11212  "var result = 0;"
11213  "o.__proto__.y = 239;"
11214  "for (var i = 0; i < 1000; i++) {"
11215  " result = o.y + o.x;"
11216  "}",
11217  239 + 42);
11218 }
11219 
11220 
11221 THREADED_TEST(InterceptorLoadICUndefined) {
11222  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11223  "var result = 0;"
11224  "for (var i = 0; i < 1000; i++) {"
11225  " result = (o.y == undefined) ? 239 : 42;"
11226  "}",
11227  239);
11228 }
11229 
11230 
11231 THREADED_TEST(InterceptorLoadICWithOverride) {
11232  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11233  "fst = new Object(); fst.__proto__ = o;"
11234  "snd = new Object(); snd.__proto__ = fst;"
11235  "var result1 = 0;"
11236  "for (var i = 0; i < 1000; i++) {"
11237  " result1 = snd.x;"
11238  "}"
11239  "fst.x = 239;"
11240  "var result = 0;"
11241  "for (var i = 0; i < 1000; i++) {"
11242  " result = snd.x;"
11243  "}"
11244  "result + result1",
11245  239 + 42);
11246 }
11247 
11248 
11249 // Test the case when we stored field into
11250 // a stub, but interceptor produced value on its own.
11251 THREADED_TEST(InterceptorLoadICFieldNotNeeded) {
11252  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11253  "proto = new Object();"
11254  "o.__proto__ = proto;"
11255  "proto.x = 239;"
11256  "for (var i = 0; i < 1000; i++) {"
11257  " o.x;"
11258  // Now it should be ICed and keep a reference to x defined on proto
11259  "}"
11260  "var result = 0;"
11261  "for (var i = 0; i < 1000; i++) {"
11262  " result += o.x;"
11263  "}"
11264  "result;",
11265  42 * 1000);
11266 }
11267 
11268 
11269 // Test the case when we stored field into
11270 // a stub, but it got invalidated later on.
11271 THREADED_TEST(InterceptorLoadICInvalidatedField) {
11272  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11273  "proto1 = new Object();"
11274  "proto2 = new Object();"
11275  "o.__proto__ = proto1;"
11276  "proto1.__proto__ = proto2;"
11277  "proto2.y = 239;"
11278  "for (var i = 0; i < 1000; i++) {"
11279  " o.y;"
11280  // Now it should be ICed and keep a reference to y defined on proto2
11281  "}"
11282  "proto1.y = 42;"
11283  "var result = 0;"
11284  "for (var i = 0; i < 1000; i++) {"
11285  " result += o.y;"
11286  "}"
11287  "result;",
11288  42 * 1000);
11289 }
11290 
11291 
11292 static int interceptor_load_not_handled_calls = 0;
11293 static void InterceptorLoadNotHandled(
11294  Local<String> name,
11296  ++interceptor_load_not_handled_calls;
11297 }
11298 
11299 
11300 // Test how post-interceptor lookups are done in the non-cacheable
11301 // case: the interceptor should not be invoked during this lookup.
11302 THREADED_TEST(InterceptorLoadICPostInterceptor) {
11303  interceptor_load_not_handled_calls = 0;
11304  CheckInterceptorLoadIC(InterceptorLoadNotHandled,
11305  "receiver = new Object();"
11306  "receiver.__proto__ = o;"
11307  "proto = new Object();"
11308  "/* Make proto a slow-case object. */"
11309  "for (var i = 0; i < 1000; i++) {"
11310  " proto[\"xxxxxxxx\" + i] = [];"
11311  "}"
11312  "proto.x = 17;"
11313  "o.__proto__ = proto;"
11314  "var result = 0;"
11315  "for (var i = 0; i < 1000; i++) {"
11316  " result += receiver.x;"
11317  "}"
11318  "result;",
11319  17 * 1000);
11320  CHECK_EQ(1000, interceptor_load_not_handled_calls);
11321 }
11322 
11323 
11324 // Test the case when we stored field into
11325 // a stub, but it got invalidated later on due to override on
11326 // global object which is between interceptor and fields' holders.
11327 THREADED_TEST(InterceptorLoadICInvalidatedFieldViaGlobal) {
11328  CheckInterceptorLoadIC(InterceptorLoadXICGetter,
11329  "o.__proto__ = this;" // set a global to be a proto of o.
11330  "this.__proto__.y = 239;"
11331  "for (var i = 0; i < 10; i++) {"
11332  " if (o.y != 239) throw 'oops: ' + o.y;"
11333  // Now it should be ICed and keep a reference to y defined on field_holder.
11334  "}"
11335  "this.y = 42;" // Assign on a global.
11336  "var result = 0;"
11337  "for (var i = 0; i < 10; i++) {"
11338  " result += o.y;"
11339  "}"
11340  "result;",
11341  42 * 10);
11342 }
11343 
11344 
11345 static void SetOnThis(Local<String> name,
11346  Local<Value> value,
11347  const v8::PropertyCallbackInfo<void>& info) {
11348  info.This()->ForceSet(name, value);
11349 }
11350 
11351 
11352 THREADED_TEST(InterceptorLoadICWithCallbackOnHolder) {
11353  v8::Isolate* isolate = CcTest::isolate();
11354  v8::HandleScope scope(isolate);
11355  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11356  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11357  templ->SetAccessor(v8_str("y"), Return239Callback);
11358  LocalContext context;
11359  context->Global()->Set(v8_str("o"), templ->NewInstance());
11360 
11361  // Check the case when receiver and interceptor's holder
11362  // are the same objects.
11363  v8::Handle<Value> value = CompileRun(
11364  "var result = 0;"
11365  "for (var i = 0; i < 7; i++) {"
11366  " result = o.y;"
11367  "}");
11368  CHECK_EQ(239, value->Int32Value());
11369 
11370  // Check the case when interceptor's holder is in proto chain
11371  // of receiver.
11372  value = CompileRun(
11373  "r = { __proto__: o };"
11374  "var result = 0;"
11375  "for (var i = 0; i < 7; i++) {"
11376  " result = r.y;"
11377  "}");
11378  CHECK_EQ(239, value->Int32Value());
11379 }
11380 
11381 
11382 THREADED_TEST(InterceptorLoadICWithCallbackOnProto) {
11383  v8::Isolate* isolate = CcTest::isolate();
11384  v8::HandleScope scope(isolate);
11385  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11386  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11387  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11388  templ_p->SetAccessor(v8_str("y"), Return239Callback);
11389 
11390  LocalContext context;
11391  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11392  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11393 
11394  // Check the case when receiver and interceptor's holder
11395  // are the same objects.
11396  v8::Handle<Value> value = CompileRun(
11397  "o.__proto__ = p;"
11398  "var result = 0;"
11399  "for (var i = 0; i < 7; i++) {"
11400  " result = o.x + o.y;"
11401  "}");
11402  CHECK_EQ(239 + 42, value->Int32Value());
11403 
11404  // Check the case when interceptor's holder is in proto chain
11405  // of receiver.
11406  value = CompileRun(
11407  "r = { __proto__: o };"
11408  "var result = 0;"
11409  "for (var i = 0; i < 7; i++) {"
11410  " result = r.x + r.y;"
11411  "}");
11412  CHECK_EQ(239 + 42, value->Int32Value());
11413 }
11414 
11415 
11416 THREADED_TEST(InterceptorLoadICForCallbackWithOverride) {
11417  v8::Isolate* isolate = CcTest::isolate();
11418  v8::HandleScope scope(isolate);
11419  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11420  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11421  templ->SetAccessor(v8_str("y"), Return239Callback);
11422 
11423  LocalContext context;
11424  context->Global()->Set(v8_str("o"), templ->NewInstance());
11425 
11426  v8::Handle<Value> value = CompileRun(
11427  "fst = new Object(); fst.__proto__ = o;"
11428  "snd = new Object(); snd.__proto__ = fst;"
11429  "var result1 = 0;"
11430  "for (var i = 0; i < 7; i++) {"
11431  " result1 = snd.x;"
11432  "}"
11433  "fst.x = 239;"
11434  "var result = 0;"
11435  "for (var i = 0; i < 7; i++) {"
11436  " result = snd.x;"
11437  "}"
11438  "result + result1");
11439  CHECK_EQ(239 + 42, value->Int32Value());
11440 }
11441 
11442 
11443 // Test the case when we stored callback into
11444 // a stub, but interceptor produced value on its own.
11445 THREADED_TEST(InterceptorLoadICCallbackNotNeeded) {
11446  v8::Isolate* isolate = CcTest::isolate();
11447  v8::HandleScope scope(isolate);
11448  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11449  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11450  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11451  templ_p->SetAccessor(v8_str("y"), Return239Callback);
11452 
11453  LocalContext context;
11454  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11455  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11456 
11457  v8::Handle<Value> value = CompileRun(
11458  "o.__proto__ = p;"
11459  "for (var i = 0; i < 7; i++) {"
11460  " o.x;"
11461  // Now it should be ICed and keep a reference to x defined on p
11462  "}"
11463  "var result = 0;"
11464  "for (var i = 0; i < 7; i++) {"
11465  " result += o.x;"
11466  "}"
11467  "result");
11468  CHECK_EQ(42 * 7, value->Int32Value());
11469 }
11470 
11471 
11472 // Test the case when we stored callback into
11473 // a stub, but it got invalidated later on.
11474 THREADED_TEST(InterceptorLoadICInvalidatedCallback) {
11475  v8::Isolate* isolate = CcTest::isolate();
11476  v8::HandleScope scope(isolate);
11477  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11478  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11479  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11480  templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
11481 
11482  LocalContext context;
11483  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11484  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11485 
11486  v8::Handle<Value> value = CompileRun(
11487  "inbetween = new Object();"
11488  "o.__proto__ = inbetween;"
11489  "inbetween.__proto__ = p;"
11490  "for (var i = 0; i < 10; i++) {"
11491  " o.y;"
11492  // Now it should be ICed and keep a reference to y defined on p
11493  "}"
11494  "inbetween.y = 42;"
11495  "var result = 0;"
11496  "for (var i = 0; i < 10; i++) {"
11497  " result += o.y;"
11498  "}"
11499  "result");
11500  CHECK_EQ(42 * 10, value->Int32Value());
11501 }
11502 
11503 
11504 // Test the case when we stored callback into
11505 // a stub, but it got invalidated later on due to override on
11506 // global object which is between interceptor and callbacks' holders.
11507 THREADED_TEST(InterceptorLoadICInvalidatedCallbackViaGlobal) {
11508  v8::Isolate* isolate = CcTest::isolate();
11509  v8::HandleScope scope(isolate);
11510  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11511  templ_o->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11512  v8::Handle<v8::ObjectTemplate> templ_p = ObjectTemplate::New(isolate);
11513  templ_p->SetAccessor(v8_str("y"), Return239Callback, SetOnThis);
11514 
11515  LocalContext context;
11516  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11517  context->Global()->Set(v8_str("p"), templ_p->NewInstance());
11518 
11519  v8::Handle<Value> value = CompileRun(
11520  "o.__proto__ = this;"
11521  "this.__proto__ = p;"
11522  "for (var i = 0; i < 10; i++) {"
11523  " if (o.y != 239) throw 'oops: ' + o.y;"
11524  // Now it should be ICed and keep a reference to y defined on p
11525  "}"
11526  "this.y = 42;"
11527  "var result = 0;"
11528  "for (var i = 0; i < 10; i++) {"
11529  " result += o.y;"
11530  "}"
11531  "result");
11532  CHECK_EQ(42 * 10, value->Int32Value());
11533 }
11534 
11535 
11536 static void InterceptorLoadICGetter0(
11537  Local<String> name,
11540  CHECK(v8_str("x")->Equals(name));
11541  info.GetReturnValue().Set(v8::Integer::New(info.GetIsolate(), 0));
11542 }
11543 
11544 
11545 THREADED_TEST(InterceptorReturningZero) {
11546  CheckInterceptorLoadIC(InterceptorLoadICGetter0,
11547  "o.x == undefined ? 1 : 0",
11548  0);
11549 }
11550 
11551 
11552 static void InterceptorStoreICSetter(
11553  Local<String> key,
11554  Local<Value> value,
11556  CHECK(v8_str("x")->Equals(key));
11557  CHECK_EQ(42, value->Int32Value());
11558  info.GetReturnValue().Set(value);
11559 }
11560 
11561 
11562 // This test should hit the store IC for the interceptor case.
11563 THREADED_TEST(InterceptorStoreIC) {
11564  v8::Isolate* isolate = CcTest::isolate();
11565  v8::HandleScope scope(isolate);
11566  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11567  templ->SetNamedPropertyHandler(InterceptorLoadICGetter,
11568  InterceptorStoreICSetter,
11569  0, 0, 0, v8_str("data"));
11570  LocalContext context;
11571  context->Global()->Set(v8_str("o"), templ->NewInstance());
11572  CompileRun(
11573  "for (var i = 0; i < 1000; i++) {"
11574  " o.x = 42;"
11575  "}");
11576 }
11577 
11578 
11579 THREADED_TEST(InterceptorStoreICWithNoSetter) {
11580  v8::Isolate* isolate = CcTest::isolate();
11581  v8::HandleScope scope(isolate);
11582  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11583  templ->SetNamedPropertyHandler(InterceptorLoadXICGetter);
11584  LocalContext context;
11585  context->Global()->Set(v8_str("o"), templ->NewInstance());
11586  v8::Handle<Value> value = CompileRun(
11587  "for (var i = 0; i < 1000; i++) {"
11588  " o.y = 239;"
11589  "}"
11590  "42 + o.y");
11591  CHECK_EQ(239 + 42, value->Int32Value());
11592 }
11593 
11594 
11595 
11596 
11600 
11601 static void InterceptorCallICGetter(
11602  Local<String> name,
11605  CHECK(v8_str("x")->Equals(name));
11606  info.GetReturnValue().Set(call_ic_function);
11607 }
11608 
11609 
11610 // This test should hit the call IC for the interceptor case.
11611 THREADED_TEST(InterceptorCallIC) {
11612  v8::Isolate* isolate = CcTest::isolate();
11613  v8::HandleScope scope(isolate);
11614  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11615  templ->SetNamedPropertyHandler(InterceptorCallICGetter);
11616  LocalContext context;
11617  context->Global()->Set(v8_str("o"), templ->NewInstance());
11618  call_ic_function =
11619  v8_compile("function f(x) { return x + 1; }; f")->Run();
11620  v8::Handle<Value> value = CompileRun(
11621  "var result = 0;"
11622  "for (var i = 0; i < 1000; i++) {"
11623  " result = o.x(41);"
11624  "}");
11625  CHECK_EQ(42, value->Int32Value());
11626 }
11627 
11628 
11629 // This test checks that if interceptor doesn't provide
11630 // a value, we can fetch regular value.
11631 THREADED_TEST(InterceptorCallICSeesOthers) {
11632  v8::Isolate* isolate = CcTest::isolate();
11633  v8::HandleScope scope(isolate);
11634  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11635  templ->SetNamedPropertyHandler(NoBlockGetterX);
11636  LocalContext context;
11637  context->Global()->Set(v8_str("o"), templ->NewInstance());
11638  v8::Handle<Value> value = CompileRun(
11639  "o.x = function f(x) { return x + 1; };"
11640  "var result = 0;"
11641  "for (var i = 0; i < 7; i++) {"
11642  " result = o.x(41);"
11643  "}");
11644  CHECK_EQ(42, value->Int32Value());
11645 }
11646 
11647 
11648 static v8::Handle<Value> call_ic_function4;
11649 static void InterceptorCallICGetter4(
11650  Local<String> name,
11653  CHECK(v8_str("x")->Equals(name));
11654  info.GetReturnValue().Set(call_ic_function4);
11655 }
11656 
11657 
11658 // This test checks that if interceptor provides a function,
11659 // even if we cached shadowed variant, interceptor's function
11660 // is invoked
11661 THREADED_TEST(InterceptorCallICCacheableNotNeeded) {
11662  v8::Isolate* isolate = CcTest::isolate();
11663  v8::HandleScope scope(isolate);
11664  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11665  templ->SetNamedPropertyHandler(InterceptorCallICGetter4);
11666  LocalContext context;
11667  context->Global()->Set(v8_str("o"), templ->NewInstance());
11668  call_ic_function4 =
11669  v8_compile("function f(x) { return x - 1; }; f")->Run();
11670  v8::Handle<Value> value = CompileRun(
11671  "Object.getPrototypeOf(o).x = function(x) { return x + 1; };"
11672  "var result = 0;"
11673  "for (var i = 0; i < 1000; i++) {"
11674  " result = o.x(42);"
11675  "}");
11676  CHECK_EQ(41, value->Int32Value());
11677 }
11678 
11679 
11680 // Test the case when we stored cacheable lookup into
11681 // a stub, but it got invalidated later on
11682 THREADED_TEST(InterceptorCallICInvalidatedCacheable) {
11683  v8::Isolate* isolate = CcTest::isolate();
11684  v8::HandleScope scope(isolate);
11685  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11686  templ->SetNamedPropertyHandler(NoBlockGetterX);
11687  LocalContext context;
11688  context->Global()->Set(v8_str("o"), templ->NewInstance());
11689  v8::Handle<Value> value = CompileRun(
11690  "proto1 = new Object();"
11691  "proto2 = new Object();"
11692  "o.__proto__ = proto1;"
11693  "proto1.__proto__ = proto2;"
11694  "proto2.y = function(x) { return x + 1; };"
11695  // Invoke it many times to compile a stub
11696  "for (var i = 0; i < 7; i++) {"
11697  " o.y(42);"
11698  "}"
11699  "proto1.y = function(x) { return x - 1; };"
11700  "var result = 0;"
11701  "for (var i = 0; i < 7; i++) {"
11702  " result += o.y(42);"
11703  "}");
11704  CHECK_EQ(41 * 7, value->Int32Value());
11705 }
11706 
11707 
11708 // This test checks that if interceptor doesn't provide a function,
11709 // cached constant function is used
11710 THREADED_TEST(InterceptorCallICConstantFunctionUsed) {
11711  v8::Isolate* isolate = CcTest::isolate();
11712  v8::HandleScope scope(isolate);
11713  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11714  templ->SetNamedPropertyHandler(NoBlockGetterX);
11715  LocalContext context;
11716  context->Global()->Set(v8_str("o"), templ->NewInstance());
11717  v8::Handle<Value> value = CompileRun(
11718  "function inc(x) { return x + 1; };"
11719  "inc(1);"
11720  "o.x = inc;"
11721  "var result = 0;"
11722  "for (var i = 0; i < 1000; i++) {"
11723  " result = o.x(42);"
11724  "}");
11725  CHECK_EQ(43, value->Int32Value());
11726 }
11727 
11728 
11729 static v8::Handle<Value> call_ic_function5;
11730 static void InterceptorCallICGetter5(
11731  Local<String> name,
11734  if (v8_str("x")->Equals(name))
11735  info.GetReturnValue().Set(call_ic_function5);
11736 }
11737 
11738 
11739 // This test checks that if interceptor provides a function,
11740 // even if we cached constant function, interceptor's function
11741 // is invoked
11742 THREADED_TEST(InterceptorCallICConstantFunctionNotNeeded) {
11743  v8::Isolate* isolate = CcTest::isolate();
11744  v8::HandleScope scope(isolate);
11745  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11746  templ->SetNamedPropertyHandler(InterceptorCallICGetter5);
11747  LocalContext context;
11748  context->Global()->Set(v8_str("o"), templ->NewInstance());
11749  call_ic_function5 =
11750  v8_compile("function f(x) { return x - 1; }; f")->Run();
11751  v8::Handle<Value> value = CompileRun(
11752  "function inc(x) { return x + 1; };"
11753  "inc(1);"
11754  "o.x = inc;"
11755  "var result = 0;"
11756  "for (var i = 0; i < 1000; i++) {"
11757  " result = o.x(42);"
11758  "}");
11759  CHECK_EQ(41, value->Int32Value());
11760 }
11761 
11762 
11763 static v8::Handle<Value> call_ic_function6;
11764 static void InterceptorCallICGetter6(
11765  Local<String> name,
11768  if (v8_str("x")->Equals(name))
11769  info.GetReturnValue().Set(call_ic_function6);
11770 }
11771 
11772 
11773 // Same test as above, except the code is wrapped in a function
11774 // to test the optimized compiler.
11775 THREADED_TEST(InterceptorCallICConstantFunctionNotNeededWrapped) {
11776  i::FLAG_allow_natives_syntax = true;
11777  v8::Isolate* isolate = CcTest::isolate();
11778  v8::HandleScope scope(isolate);
11779  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11780  templ->SetNamedPropertyHandler(InterceptorCallICGetter6);
11781  LocalContext context;
11782  context->Global()->Set(v8_str("o"), templ->NewInstance());
11783  call_ic_function6 =
11784  v8_compile("function f(x) { return x - 1; }; f")->Run();
11785  v8::Handle<Value> value = CompileRun(
11786  "function inc(x) { return x + 1; };"
11787  "inc(1);"
11788  "o.x = inc;"
11789  "function test() {"
11790  " var result = 0;"
11791  " for (var i = 0; i < 1000; i++) {"
11792  " result = o.x(42);"
11793  " }"
11794  " return result;"
11795  "};"
11796  "test();"
11797  "test();"
11798  "test();"
11799  "%OptimizeFunctionOnNextCall(test);"
11800  "test()");
11801  CHECK_EQ(41, value->Int32Value());
11802 }
11803 
11804 
11805 // Test the case when we stored constant function into
11806 // a stub, but it got invalidated later on
11807 THREADED_TEST(InterceptorCallICInvalidatedConstantFunction) {
11808  v8::Isolate* isolate = CcTest::isolate();
11809  v8::HandleScope scope(isolate);
11810  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11811  templ->SetNamedPropertyHandler(NoBlockGetterX);
11812  LocalContext context;
11813  context->Global()->Set(v8_str("o"), templ->NewInstance());
11814  v8::Handle<Value> value = CompileRun(
11815  "function inc(x) { return x + 1; };"
11816  "inc(1);"
11817  "proto1 = new Object();"
11818  "proto2 = new Object();"
11819  "o.__proto__ = proto1;"
11820  "proto1.__proto__ = proto2;"
11821  "proto2.y = inc;"
11822  // Invoke it many times to compile a stub
11823  "for (var i = 0; i < 7; i++) {"
11824  " o.y(42);"
11825  "}"
11826  "proto1.y = function(x) { return x - 1; };"
11827  "var result = 0;"
11828  "for (var i = 0; i < 7; i++) {"
11829  " result += o.y(42);"
11830  "}");
11831  CHECK_EQ(41 * 7, value->Int32Value());
11832 }
11833 
11834 
11835 // Test the case when we stored constant function into
11836 // a stub, but it got invalidated later on due to override on
11837 // global object which is between interceptor and constant function' holders.
11838 THREADED_TEST(InterceptorCallICInvalidatedConstantFunctionViaGlobal) {
11839  v8::Isolate* isolate = CcTest::isolate();
11840  v8::HandleScope scope(isolate);
11841  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
11842  templ->SetNamedPropertyHandler(NoBlockGetterX);
11843  LocalContext context;
11844  context->Global()->Set(v8_str("o"), templ->NewInstance());
11845  v8::Handle<Value> value = CompileRun(
11846  "function inc(x) { return x + 1; };"
11847  "inc(1);"
11848  "o.__proto__ = this;"
11849  "this.__proto__.y = inc;"
11850  // Invoke it many times to compile a stub
11851  "for (var i = 0; i < 7; i++) {"
11852  " if (o.y(42) != 43) throw 'oops: ' + o.y(42);"
11853  "}"
11854  "this.y = function(x) { return x - 1; };"
11855  "var result = 0;"
11856  "for (var i = 0; i < 7; i++) {"
11857  " result += o.y(42);"
11858  "}");
11859  CHECK_EQ(41 * 7, value->Int32Value());
11860 }
11861 
11862 
11863 // Test the case when actual function to call sits on global object.
11864 THREADED_TEST(InterceptorCallICCachedFromGlobal) {
11865  v8::Isolate* isolate = CcTest::isolate();
11866  v8::HandleScope scope(isolate);
11867  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
11868  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
11869 
11870  LocalContext context;
11871  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
11872 
11873  v8::Handle<Value> value = CompileRun(
11874  "try {"
11875  " o.__proto__ = this;"
11876  " for (var i = 0; i < 10; i++) {"
11877  " var v = o.parseFloat('239');"
11878  " if (v != 239) throw v;"
11879  // Now it should be ICed and keep a reference to parseFloat.
11880  " }"
11881  " var result = 0;"
11882  " for (var i = 0; i < 10; i++) {"
11883  " result += o.parseFloat('239');"
11884  " }"
11885  " result"
11886  "} catch(e) {"
11887  " e"
11888  "};");
11889  CHECK_EQ(239 * 10, value->Int32Value());
11890 }
11891 
11892 static void InterceptorCallICFastApi(
11893  Local<String> name,
11896  CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
11897  int* call_count =
11898  reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
11899  ++(*call_count);
11900  if ((*call_count) % 20 == 0) {
11902  }
11903 }
11904 
11905 static void FastApiCallback_TrivialSignature(
11908  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
11909  v8::Isolate* isolate = CcTest::isolate();
11910  CHECK_EQ(isolate, args.GetIsolate());
11911  CHECK_EQ(args.This(), args.Holder());
11912  CHECK(args.Data()->Equals(v8_str("method_data")));
11913  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
11914 }
11915 
11916 static void FastApiCallback_SimpleSignature(
11919  CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
11920  v8::Isolate* isolate = CcTest::isolate();
11921  CHECK_EQ(isolate, args.GetIsolate());
11922  CHECK_EQ(args.This()->GetPrototype(), args.Holder());
11923  CHECK(args.Data()->Equals(v8_str("method_data")));
11924  // Note, we're using HasRealNamedProperty instead of Has to avoid
11925  // invoking the interceptor again.
11926  CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
11927  args.GetReturnValue().Set(args[0]->Int32Value() + 1);
11928 }
11929 
11930 
11931 // Helper to maximize the odds of object moving.
11932 static void GenerateSomeGarbage() {
11933  CompileRun(
11934  "var garbage;"
11935  "for (var i = 0; i < 1000; i++) {"
11936  " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
11937  "}"
11938  "garbage = undefined;");
11939 }
11940 
11941 
11943  static int count = 0;
11944  if (count++ % 3 == 0) {
11946  // This should move the stub
11947  GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
11948  }
11949 }
11950 
11951 
11952 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
11953  LocalContext context;
11954  v8::Isolate* isolate = context->GetIsolate();
11955  v8::HandleScope scope(isolate);
11956  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
11957  v8::ObjectTemplate::New(isolate);
11958  nativeobject_templ->Set(isolate, "callback",
11959  v8::FunctionTemplate::New(isolate,
11961  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11962  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11963  // call the api function multiple times to ensure direct call stub creation.
11964  CompileRun(
11965  "function f() {"
11966  " for (var i = 1; i <= 30; i++) {"
11967  " nativeobject.callback();"
11968  " }"
11969  "}"
11970  "f();");
11971 }
11972 
11973 
11976  args.GetIsolate()->ThrowException(v8_str("g"));
11977 }
11978 
11979 
11980 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
11981  LocalContext context;
11982  v8::Isolate* isolate = context->GetIsolate();
11983  v8::HandleScope scope(isolate);
11984  v8::Handle<v8::ObjectTemplate> nativeobject_templ =
11985  v8::ObjectTemplate::New(isolate);
11986  nativeobject_templ->Set(isolate, "callback",
11987  v8::FunctionTemplate::New(isolate,
11989  v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
11990  context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
11991  // call the api function multiple times to ensure direct call stub creation.
11992  v8::Handle<Value> result = CompileRun(
11993  "var result = '';"
11994  "function f() {"
11995  " for (var i = 1; i <= 5; i++) {"
11996  " try { nativeobject.callback(); } catch (e) { result += e; }"
11997  " }"
11998  "}"
11999  "f(); result;");
12000  CHECK_EQ(v8_str("ggggg"), result);
12001 }
12002 
12003 
12004 static Handle<Value> DoDirectGetter() {
12005  if (++p_getter_count % 3 == 0) {
12007  GenerateSomeGarbage();
12008  }
12009  return v8_str("Direct Getter Result");
12010 }
12011 
12012 static void DirectGetterCallback(
12013  Local<String> name,
12015  CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
12016  info.GetReturnValue().Set(DoDirectGetter());
12017 }
12018 
12019 
12020 template<typename Accessor>
12021 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
12022  LocalContext context;
12023  v8::Isolate* isolate = context->GetIsolate();
12024  v8::HandleScope scope(isolate);
12026  obj->SetAccessor(v8_str("p1"), accessor);
12027  context->Global()->Set(v8_str("o1"), obj->NewInstance());
12028  p_getter_count = 0;
12029  v8::Handle<v8::Value> result = CompileRun(
12030  "function f() {"
12031  " for (var i = 0; i < 30; i++) o1.p1;"
12032  " return o1.p1"
12033  "}"
12034  "f();");
12035  CHECK_EQ(v8_str("Direct Getter Result"), result);
12036  CHECK_EQ(31, p_getter_count);
12037 }
12038 
12039 
12040 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
12041  LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
12042 }
12043 
12044 
12046  Local<String> name,
12048  info.GetIsolate()->ThrowException(v8_str("g"));
12049 }
12050 
12051 
12052 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
12053  LocalContext context;
12054  v8::Isolate* isolate = context->GetIsolate();
12055  v8::HandleScope scope(isolate);
12057  obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
12058  context->Global()->Set(v8_str("o1"), obj->NewInstance());
12059  v8::Handle<Value> result = CompileRun(
12060  "var result = '';"
12061  "for (var i = 0; i < 5; i++) {"
12062  " try { o1.p1; } catch (e) { result += e; }"
12063  "}"
12064  "result;");
12065  CHECK_EQ(v8_str("ggggg"), result);
12066 }
12067 
12068 
12069 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
12070  int interceptor_call_count = 0;
12071  v8::Isolate* isolate = CcTest::isolate();
12072  v8::HandleScope scope(isolate);
12074  v8::FunctionTemplate::New(isolate);
12075  v8::Handle<v8::FunctionTemplate> method_templ =
12076  v8::FunctionTemplate::New(isolate,
12077  FastApiCallback_TrivialSignature,
12078  v8_str("method_data"),
12080  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12081  proto_templ->Set(v8_str("method"), method_templ);
12082  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12083  templ->SetNamedPropertyHandler(
12084  InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12085  v8::External::New(isolate, &interceptor_call_count));
12086  LocalContext context;
12087  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12088  GenerateSomeGarbage();
12089  context->Global()->Set(v8_str("o"), fun->NewInstance());
12090  CompileRun(
12091  "var result = 0;"
12092  "for (var i = 0; i < 100; i++) {"
12093  " result = o.method(41);"
12094  "}");
12095  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12096  CHECK_EQ(100, interceptor_call_count);
12097 }
12098 
12099 
12100 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
12101  int interceptor_call_count = 0;
12102  v8::Isolate* isolate = CcTest::isolate();
12103  v8::HandleScope scope(isolate);
12105  v8::FunctionTemplate::New(isolate);
12107  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12108  v8::Signature::New(isolate, fun_templ));
12109  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12110  proto_templ->Set(v8_str("method"), method_templ);
12111  fun_templ->SetHiddenPrototype(true);
12112  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12113  templ->SetNamedPropertyHandler(
12114  InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12115  v8::External::New(isolate, &interceptor_call_count));
12116  LocalContext context;
12117  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12118  GenerateSomeGarbage();
12119  context->Global()->Set(v8_str("o"), fun->NewInstance());
12120  CompileRun(
12121  "o.foo = 17;"
12122  "var receiver = {};"
12123  "receiver.__proto__ = o;"
12124  "var result = 0;"
12125  "for (var i = 0; i < 100; i++) {"
12126  " result = receiver.method(41);"
12127  "}");
12128  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12129  CHECK_EQ(100, interceptor_call_count);
12130 }
12131 
12132 
12133 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
12134  int interceptor_call_count = 0;
12135  v8::Isolate* isolate = CcTest::isolate();
12136  v8::HandleScope scope(isolate);
12138  v8::FunctionTemplate::New(isolate);
12140  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12141  v8::Signature::New(isolate, fun_templ));
12142  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12143  proto_templ->Set(v8_str("method"), method_templ);
12144  fun_templ->SetHiddenPrototype(true);
12145  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12146  templ->SetNamedPropertyHandler(
12147  InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12148  v8::External::New(isolate, &interceptor_call_count));
12149  LocalContext context;
12150  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12151  GenerateSomeGarbage();
12152  context->Global()->Set(v8_str("o"), fun->NewInstance());
12153  CompileRun(
12154  "o.foo = 17;"
12155  "var receiver = {};"
12156  "receiver.__proto__ = o;"
12157  "var result = 0;"
12158  "var saved_result = 0;"
12159  "for (var i = 0; i < 100; i++) {"
12160  " result = receiver.method(41);"
12161  " if (i == 50) {"
12162  " saved_result = result;"
12163  " receiver = {method: function(x) { return x - 1 }};"
12164  " }"
12165  "}");
12166  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12167  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12168  CHECK_GE(interceptor_call_count, 50);
12169 }
12170 
12171 
12172 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
12173  int interceptor_call_count = 0;
12174  v8::Isolate* isolate = CcTest::isolate();
12175  v8::HandleScope scope(isolate);
12177  v8::FunctionTemplate::New(isolate);
12179  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12180  v8::Signature::New(isolate, fun_templ));
12181  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12182  proto_templ->Set(v8_str("method"), method_templ);
12183  fun_templ->SetHiddenPrototype(true);
12184  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12185  templ->SetNamedPropertyHandler(
12186  InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12187  v8::External::New(isolate, &interceptor_call_count));
12188  LocalContext context;
12189  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12190  GenerateSomeGarbage();
12191  context->Global()->Set(v8_str("o"), fun->NewInstance());
12192  CompileRun(
12193  "o.foo = 17;"
12194  "var receiver = {};"
12195  "receiver.__proto__ = o;"
12196  "var result = 0;"
12197  "var saved_result = 0;"
12198  "for (var i = 0; i < 100; i++) {"
12199  " result = receiver.method(41);"
12200  " if (i == 50) {"
12201  " saved_result = result;"
12202  " o.method = function(x) { return x - 1 };"
12203  " }"
12204  "}");
12205  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12206  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12207  CHECK_GE(interceptor_call_count, 50);
12208 }
12209 
12210 
12211 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
12212  int interceptor_call_count = 0;
12213  v8::Isolate* isolate = CcTest::isolate();
12214  v8::HandleScope scope(isolate);
12216  v8::FunctionTemplate::New(isolate);
12218  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12219  v8::Signature::New(isolate, fun_templ));
12220  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12221  proto_templ->Set(v8_str("method"), method_templ);
12222  fun_templ->SetHiddenPrototype(true);
12223  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12224  templ->SetNamedPropertyHandler(
12225  InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12226  v8::External::New(isolate, &interceptor_call_count));
12227  LocalContext context;
12228  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12229  GenerateSomeGarbage();
12230  context->Global()->Set(v8_str("o"), fun->NewInstance());
12231  v8::TryCatch try_catch;
12232  CompileRun(
12233  "o.foo = 17;"
12234  "var receiver = {};"
12235  "receiver.__proto__ = o;"
12236  "var result = 0;"
12237  "var saved_result = 0;"
12238  "for (var i = 0; i < 100; i++) {"
12239  " result = receiver.method(41);"
12240  " if (i == 50) {"
12241  " saved_result = result;"
12242  " receiver = 333;"
12243  " }"
12244  "}");
12245  CHECK(try_catch.HasCaught());
12246  // TODO(verwaest): Adjust message.
12247  CHECK_EQ(v8_str("TypeError: undefined is not a function"),
12248  try_catch.Exception()->ToString());
12249  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12250  CHECK_GE(interceptor_call_count, 50);
12251 }
12252 
12253 
12254 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
12255  int interceptor_call_count = 0;
12256  v8::Isolate* isolate = CcTest::isolate();
12257  v8::HandleScope scope(isolate);
12259  v8::FunctionTemplate::New(isolate);
12261  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12262  v8::Signature::New(isolate, fun_templ));
12263  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12264  proto_templ->Set(v8_str("method"), method_templ);
12265  fun_templ->SetHiddenPrototype(true);
12266  v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
12267  templ->SetNamedPropertyHandler(
12268  InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
12269  v8::External::New(isolate, &interceptor_call_count));
12270  LocalContext context;
12271  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12272  GenerateSomeGarbage();
12273  context->Global()->Set(v8_str("o"), fun->NewInstance());
12274  v8::TryCatch try_catch;
12275  CompileRun(
12276  "o.foo = 17;"
12277  "var receiver = {};"
12278  "receiver.__proto__ = o;"
12279  "var result = 0;"
12280  "var saved_result = 0;"
12281  "for (var i = 0; i < 100; i++) {"
12282  " result = receiver.method(41);"
12283  " if (i == 50) {"
12284  " saved_result = result;"
12285  " receiver = {method: receiver.method};"
12286  " }"
12287  "}");
12288  CHECK(try_catch.HasCaught());
12289  CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12290  try_catch.Exception()->ToString());
12291  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12292  CHECK_GE(interceptor_call_count, 50);
12293 }
12294 
12295 
12296 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
12297  v8::Isolate* isolate = CcTest::isolate();
12298  v8::HandleScope scope(isolate);
12300  v8::FunctionTemplate::New(isolate);
12301  v8::Handle<v8::FunctionTemplate> method_templ =
12302  v8::FunctionTemplate::New(isolate,
12303  FastApiCallback_TrivialSignature,
12304  v8_str("method_data"),
12306  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12307  proto_templ->Set(v8_str("method"), method_templ);
12309  USE(templ);
12310  LocalContext context;
12311  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12312  GenerateSomeGarbage();
12313  context->Global()->Set(v8_str("o"), fun->NewInstance());
12314  CompileRun(
12315  "var result = 0;"
12316  "for (var i = 0; i < 100; i++) {"
12317  " result = o.method(41);"
12318  "}");
12319 
12320  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12321 }
12322 
12323 
12324 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
12325  v8::Isolate* isolate = CcTest::isolate();
12326  v8::HandleScope scope(isolate);
12328  v8::FunctionTemplate::New(isolate);
12330  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12331  v8::Signature::New(isolate, fun_templ));
12332  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12333  proto_templ->Set(v8_str("method"), method_templ);
12334  fun_templ->SetHiddenPrototype(true);
12336  CHECK(!templ.IsEmpty());
12337  LocalContext context;
12338  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12339  GenerateSomeGarbage();
12340  context->Global()->Set(v8_str("o"), fun->NewInstance());
12341  CompileRun(
12342  "o.foo = 17;"
12343  "var receiver = {};"
12344  "receiver.__proto__ = o;"
12345  "var result = 0;"
12346  "for (var i = 0; i < 100; i++) {"
12347  " result = receiver.method(41);"
12348  "}");
12349 
12350  CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
12351 }
12352 
12353 
12354 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
12355  v8::Isolate* isolate = CcTest::isolate();
12356  v8::HandleScope scope(isolate);
12358  v8::FunctionTemplate::New(isolate);
12360  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12361  v8::Signature::New(isolate, fun_templ));
12362  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12363  proto_templ->Set(v8_str("method"), method_templ);
12364  fun_templ->SetHiddenPrototype(true);
12366  CHECK(!templ.IsEmpty());
12367  LocalContext context;
12368  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12369  GenerateSomeGarbage();
12370  context->Global()->Set(v8_str("o"), fun->NewInstance());
12371  CompileRun(
12372  "o.foo = 17;"
12373  "var receiver = {};"
12374  "receiver.__proto__ = o;"
12375  "var result = 0;"
12376  "var saved_result = 0;"
12377  "for (var i = 0; i < 100; i++) {"
12378  " result = receiver.method(41);"
12379  " if (i == 50) {"
12380  " saved_result = result;"
12381  " receiver = {method: function(x) { return x - 1 }};"
12382  " }"
12383  "}");
12384  CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
12385  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12386 }
12387 
12388 
12389 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
12390  v8::Isolate* isolate = CcTest::isolate();
12391  v8::HandleScope scope(isolate);
12393  v8::FunctionTemplate::New(isolate);
12395  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12396  v8::Signature::New(isolate, fun_templ));
12397  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12398  proto_templ->Set(v8_str("method"), method_templ);
12399  fun_templ->SetHiddenPrototype(true);
12401  CHECK(!templ.IsEmpty());
12402  LocalContext context;
12403  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12404  GenerateSomeGarbage();
12405  context->Global()->Set(v8_str("o"), fun->NewInstance());
12406  v8::TryCatch try_catch;
12407  CompileRun(
12408  "o.foo = 17;"
12409  "var receiver = {};"
12410  "receiver.__proto__ = o;"
12411  "var result = 0;"
12412  "var saved_result = 0;"
12413  "for (var i = 0; i < 100; i++) {"
12414  " result = receiver.method(41);"
12415  " if (i == 50) {"
12416  " saved_result = result;"
12417  " receiver = 333;"
12418  " }"
12419  "}");
12420  CHECK(try_catch.HasCaught());
12421  // TODO(verwaest): Adjust message.
12422  CHECK_EQ(v8_str("TypeError: undefined is not a function"),
12423  try_catch.Exception()->ToString());
12424  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12425 }
12426 
12427 
12428 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
12429  v8::Isolate* isolate = CcTest::isolate();
12430  v8::HandleScope scope(isolate);
12432  v8::FunctionTemplate::New(isolate);
12434  isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
12435  v8::Signature::New(isolate, fun_templ));
12436  v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
12437  proto_templ->Set(v8_str("method"), method_templ);
12438  fun_templ->SetHiddenPrototype(true);
12440  CHECK(!templ.IsEmpty());
12441  LocalContext context;
12442  v8::Handle<v8::Function> fun = fun_templ->GetFunction();
12443  GenerateSomeGarbage();
12444  context->Global()->Set(v8_str("o"), fun->NewInstance());
12445  v8::TryCatch try_catch;
12446  CompileRun(
12447  "o.foo = 17;"
12448  "var receiver = {};"
12449  "receiver.__proto__ = o;"
12450  "var result = 0;"
12451  "var saved_result = 0;"
12452  "for (var i = 0; i < 100; i++) {"
12453  " result = receiver.method(41);"
12454  " if (i == 50) {"
12455  " saved_result = result;"
12456  " receiver = Object.create(receiver);"
12457  " }"
12458  "}");
12459  CHECK(try_catch.HasCaught());
12460  CHECK_EQ(v8_str("TypeError: Illegal invocation"),
12461  try_catch.Exception()->ToString());
12462  CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12463 }
12464 
12465 
12467 
12468 static void InterceptorKeyedCallICGetter(
12469  Local<String> name,
12472  if (v8_str("x")->Equals(name)) {
12473  info.GetReturnValue().Set(keyed_call_ic_function);
12474  }
12475 }
12476 
12477 
12478 // Test the case when we stored cacheable lookup into
12479 // a stub, but the function name changed (to another cacheable function).
12480 THREADED_TEST(InterceptorKeyedCallICKeyChange1) {
12481  v8::Isolate* isolate = CcTest::isolate();
12482  v8::HandleScope scope(isolate);
12483  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12484  templ->SetNamedPropertyHandler(NoBlockGetterX);
12485  LocalContext context;
12486  context->Global()->Set(v8_str("o"), templ->NewInstance());
12487  CompileRun(
12488  "proto = new Object();"
12489  "proto.y = function(x) { return x + 1; };"
12490  "proto.z = function(x) { return x - 1; };"
12491  "o.__proto__ = proto;"
12492  "var result = 0;"
12493  "var method = 'y';"
12494  "for (var i = 0; i < 10; i++) {"
12495  " if (i == 5) { method = 'z'; };"
12496  " result += o[method](41);"
12497  "}");
12498  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12499 }
12500 
12501 
12502 // Test the case when we stored cacheable lookup into
12503 // a stub, but the function name changed (and the new function is present
12504 // both before and after the interceptor in the prototype chain).
12505 THREADED_TEST(InterceptorKeyedCallICKeyChange2) {
12506  v8::Isolate* isolate = CcTest::isolate();
12507  v8::HandleScope scope(isolate);
12508  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12509  templ->SetNamedPropertyHandler(InterceptorKeyedCallICGetter);
12510  LocalContext context;
12511  context->Global()->Set(v8_str("proto1"), templ->NewInstance());
12512  keyed_call_ic_function =
12513  v8_compile("function f(x) { return x - 1; }; f")->Run();
12514  CompileRun(
12515  "o = new Object();"
12516  "proto2 = new Object();"
12517  "o.y = function(x) { return x + 1; };"
12518  "proto2.y = function(x) { return x + 2; };"
12519  "o.__proto__ = proto1;"
12520  "proto1.__proto__ = proto2;"
12521  "var result = 0;"
12522  "var method = 'x';"
12523  "for (var i = 0; i < 10; i++) {"
12524  " if (i == 5) { method = 'y'; };"
12525  " result += o[method](41);"
12526  "}");
12527  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12528 }
12529 
12530 
12531 // Same as InterceptorKeyedCallICKeyChange1 only the cacheable function sit
12532 // on the global object.
12533 THREADED_TEST(InterceptorKeyedCallICKeyChangeOnGlobal) {
12534  v8::Isolate* isolate = CcTest::isolate();
12535  v8::HandleScope scope(isolate);
12536  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12537  templ->SetNamedPropertyHandler(NoBlockGetterX);
12538  LocalContext context;
12539  context->Global()->Set(v8_str("o"), templ->NewInstance());
12540  CompileRun(
12541  "function inc(x) { return x + 1; };"
12542  "inc(1);"
12543  "function dec(x) { return x - 1; };"
12544  "dec(1);"
12545  "o.__proto__ = this;"
12546  "this.__proto__.x = inc;"
12547  "this.__proto__.y = dec;"
12548  "var result = 0;"
12549  "var method = 'x';"
12550  "for (var i = 0; i < 10; i++) {"
12551  " if (i == 5) { method = 'y'; };"
12552  " result += o[method](41);"
12553  "}");
12554  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12555 }
12556 
12557 
12558 // Test the case when actual function to call sits on global object.
12559 THREADED_TEST(InterceptorKeyedCallICFromGlobal) {
12560  v8::Isolate* isolate = CcTest::isolate();
12561  v8::HandleScope scope(isolate);
12562  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
12563  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12564  LocalContext context;
12565  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12566 
12567  CompileRun(
12568  "function len(x) { return x.length; };"
12569  "o.__proto__ = this;"
12570  "var m = 'parseFloat';"
12571  "var result = 0;"
12572  "for (var i = 0; i < 10; i++) {"
12573  " if (i == 5) {"
12574  " m = 'len';"
12575  " saved_result = result;"
12576  " };"
12577  " result = o[m]('239');"
12578  "}");
12579  CHECK_EQ(3, context->Global()->Get(v8_str("result"))->Int32Value());
12580  CHECK_EQ(239, context->Global()->Get(v8_str("saved_result"))->Int32Value());
12581 }
12582 
12583 
12584 // Test the map transition before the interceptor.
12585 THREADED_TEST(InterceptorKeyedCallICMapChangeBefore) {
12586  v8::Isolate* isolate = CcTest::isolate();
12587  v8::HandleScope scope(isolate);
12588  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
12589  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12590  LocalContext context;
12591  context->Global()->Set(v8_str("proto"), templ_o->NewInstance());
12592 
12593  CompileRun(
12594  "var o = new Object();"
12595  "o.__proto__ = proto;"
12596  "o.method = function(x) { return x + 1; };"
12597  "var m = 'method';"
12598  "var result = 0;"
12599  "for (var i = 0; i < 10; i++) {"
12600  " if (i == 5) { o.method = function(x) { return x - 1; }; };"
12601  " result += o[m](41);"
12602  "}");
12603  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12604 }
12605 
12606 
12607 // Test the map transition after the interceptor.
12608 THREADED_TEST(InterceptorKeyedCallICMapChangeAfter) {
12609  v8::Isolate* isolate = CcTest::isolate();
12610  v8::HandleScope scope(isolate);
12611  v8::Handle<v8::ObjectTemplate> templ_o = ObjectTemplate::New(isolate);
12612  templ_o->SetNamedPropertyHandler(NoBlockGetterX);
12613  LocalContext context;
12614  context->Global()->Set(v8_str("o"), templ_o->NewInstance());
12615 
12616  CompileRun(
12617  "var proto = new Object();"
12618  "o.__proto__ = proto;"
12619  "proto.method = function(x) { return x + 1; };"
12620  "var m = 'method';"
12621  "var result = 0;"
12622  "for (var i = 0; i < 10; i++) {"
12623  " if (i == 5) { proto.method = function(x) { return x - 1; }; };"
12624  " result += o[m](41);"
12625  "}");
12626  CHECK_EQ(42*5 + 40*5, context->Global()->Get(v8_str("result"))->Int32Value());
12627 }
12628 
12629 
12630 static int interceptor_call_count = 0;
12631 
12632 static void InterceptorICRefErrorGetter(
12633  Local<String> name,
12636  if (v8_str("x")->Equals(name) && interceptor_call_count++ < 20) {
12637  info.GetReturnValue().Set(call_ic_function2);
12638  }
12639 }
12640 
12641 
12642 // This test should hit load and call ICs for the interceptor case.
12643 // Once in a while, the interceptor will reply that a property was not
12644 // found in which case we should get a reference error.
12645 THREADED_TEST(InterceptorICReferenceErrors) {
12646  v8::Isolate* isolate = CcTest::isolate();
12647  v8::HandleScope scope(isolate);
12648  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12649  templ->SetNamedPropertyHandler(InterceptorICRefErrorGetter);
12650  LocalContext context(0, templ, v8::Handle<Value>());
12651  call_ic_function2 = v8_compile("function h(x) { return x; }; h")->Run();
12652  v8::Handle<Value> value = CompileRun(
12653  "function f() {"
12654  " for (var i = 0; i < 1000; i++) {"
12655  " try { x; } catch(e) { return true; }"
12656  " }"
12657  " return false;"
12658  "};"
12659  "f();");
12660  CHECK_EQ(true, value->BooleanValue());
12661  interceptor_call_count = 0;
12662  value = CompileRun(
12663  "function g() {"
12664  " for (var i = 0; i < 1000; i++) {"
12665  " try { x(42); } catch(e) { return true; }"
12666  " }"
12667  " return false;"
12668  "};"
12669  "g();");
12670  CHECK_EQ(true, value->BooleanValue());
12671 }
12672 
12673 
12674 static int interceptor_ic_exception_get_count = 0;
12675 
12676 static void InterceptorICExceptionGetter(
12677  Local<String> name,
12680  if (v8_str("x")->Equals(name) && ++interceptor_ic_exception_get_count < 20) {
12681  info.GetReturnValue().Set(call_ic_function3);
12682  }
12683  if (interceptor_ic_exception_get_count == 20) {
12684  info.GetIsolate()->ThrowException(v8_num(42));
12685  return;
12686  }
12687 }
12688 
12689 
12690 // Test interceptor load/call IC where the interceptor throws an
12691 // exception once in a while.
12692 THREADED_TEST(InterceptorICGetterExceptions) {
12693  interceptor_ic_exception_get_count = 0;
12694  v8::Isolate* isolate = CcTest::isolate();
12695  v8::HandleScope scope(isolate);
12696  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12697  templ->SetNamedPropertyHandler(InterceptorICExceptionGetter);
12698  LocalContext context(0, templ, v8::Handle<Value>());
12699  call_ic_function3 = v8_compile("function h(x) { return x; }; h")->Run();
12700  v8::Handle<Value> value = CompileRun(
12701  "function f() {"
12702  " for (var i = 0; i < 100; i++) {"
12703  " try { x; } catch(e) { return true; }"
12704  " }"
12705  " return false;"
12706  "};"
12707  "f();");
12708  CHECK_EQ(true, value->BooleanValue());
12709  interceptor_ic_exception_get_count = 0;
12710  value = CompileRun(
12711  "function f() {"
12712  " for (var i = 0; i < 100; i++) {"
12713  " try { x(42); } catch(e) { return true; }"
12714  " }"
12715  " return false;"
12716  "};"
12717  "f();");
12718  CHECK_EQ(true, value->BooleanValue());
12719 }
12720 
12721 
12722 static int interceptor_ic_exception_set_count = 0;
12723 
12724 static void InterceptorICExceptionSetter(
12725  Local<String> key,
12726  Local<Value> value,
12729  if (++interceptor_ic_exception_set_count > 20) {
12730  info.GetIsolate()->ThrowException(v8_num(42));
12731  }
12732 }
12733 
12734 
12735 // Test interceptor store IC where the interceptor throws an exception
12736 // once in a while.
12737 THREADED_TEST(InterceptorICSetterExceptions) {
12738  interceptor_ic_exception_set_count = 0;
12739  v8::Isolate* isolate = CcTest::isolate();
12740  v8::HandleScope scope(isolate);
12741  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12742  templ->SetNamedPropertyHandler(0, InterceptorICExceptionSetter);
12743  LocalContext context(0, templ, v8::Handle<Value>());
12744  v8::Handle<Value> value = CompileRun(
12745  "function f() {"
12746  " for (var i = 0; i < 100; i++) {"
12747  " try { x = 42; } catch(e) { return true; }"
12748  " }"
12749  " return false;"
12750  "};"
12751  "f();");
12752  CHECK_EQ(true, value->BooleanValue());
12753 }
12754 
12755 
12756 // Test that we ignore null interceptors.
12757 THREADED_TEST(NullNamedInterceptor) {
12758  v8::Isolate* isolate = CcTest::isolate();
12759  v8::HandleScope scope(isolate);
12760  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12761  templ->SetNamedPropertyHandler(
12762  static_cast<v8::NamedPropertyGetterCallback>(0));
12763  LocalContext context;
12764  templ->Set(CcTest::isolate(), "x", v8_num(42));
12765  v8::Handle<v8::Object> obj = templ->NewInstance();
12766  context->Global()->Set(v8_str("obj"), obj);
12767  v8::Handle<Value> value = CompileRun("obj.x");
12768  CHECK(value->IsInt32());
12769  CHECK_EQ(42, value->Int32Value());
12770 }
12771 
12772 
12773 // Test that we ignore null interceptors.
12774 THREADED_TEST(NullIndexedInterceptor) {
12775  v8::Isolate* isolate = CcTest::isolate();
12776  v8::HandleScope scope(isolate);
12777  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
12779  static_cast<v8::IndexedPropertyGetterCallback>(0));
12780  LocalContext context;
12781  templ->Set(CcTest::isolate(), "42", v8_num(42));
12782  v8::Handle<v8::Object> obj = templ->NewInstance();
12783  context->Global()->Set(v8_str("obj"), obj);
12784  v8::Handle<Value> value = CompileRun("obj[42]");
12785  CHECK(value->IsInt32());
12786  CHECK_EQ(42, value->Int32Value());
12787 }
12788 
12789 
12790 THREADED_TEST(NamedPropertyHandlerGetterAttributes) {
12791  v8::Isolate* isolate = CcTest::isolate();
12792  v8::HandleScope scope(isolate);
12794  templ->InstanceTemplate()->SetNamedPropertyHandler(InterceptorLoadXICGetter);
12795  LocalContext env;
12796  env->Global()->Set(v8_str("obj"),
12797  templ->GetFunction()->NewInstance());
12798  ExpectTrue("obj.x === 42");
12799  ExpectTrue("!obj.propertyIsEnumerable('x')");
12800 }
12801 
12802 
12803 static void ThrowingGetter(Local<String> name,
12806  info.GetIsolate()->ThrowException(Handle<Value>());
12807  info.GetReturnValue().SetUndefined();
12808 }
12809 
12810 
12811 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
12812  LocalContext context;
12813  HandleScope scope(context->GetIsolate());
12814 
12815  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
12816  Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
12817  instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
12818 
12819  Local<Object> instance = templ->GetFunction()->NewInstance();
12820 
12821  Local<Object> another = Object::New(context->GetIsolate());
12822  another->SetPrototype(instance);
12823 
12824  Local<Object> with_js_getter = CompileRun(
12825  "o = {};\n"
12826  "o.__defineGetter__('f', function() { throw undefined; });\n"
12827  "o\n").As<Object>();
12828  CHECK(!with_js_getter.IsEmpty());
12829 
12830  TryCatch try_catch;
12831 
12832  Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
12833  CHECK(try_catch.HasCaught());
12834  try_catch.Reset();
12835  CHECK(result.IsEmpty());
12836 
12837  result = another->GetRealNamedProperty(v8_str("f"));
12838  CHECK(try_catch.HasCaught());
12839  try_catch.Reset();
12840  CHECK(result.IsEmpty());
12841 
12842  result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
12843  CHECK(try_catch.HasCaught());
12844  try_catch.Reset();
12845  CHECK(result.IsEmpty());
12846 
12847  result = another->Get(v8_str("f"));
12848  CHECK(try_catch.HasCaught());
12849  try_catch.Reset();
12850  CHECK(result.IsEmpty());
12851 
12852  result = with_js_getter->GetRealNamedProperty(v8_str("f"));
12853  CHECK(try_catch.HasCaught());
12854  try_catch.Reset();
12855  CHECK(result.IsEmpty());
12856 
12857  result = with_js_getter->Get(v8_str("f"));
12858  CHECK(try_catch.HasCaught());
12859  try_catch.Reset();
12860  CHECK(result.IsEmpty());
12861 }
12862 
12863 
12864 static void ThrowingCallbackWithTryCatch(
12866  TryCatch try_catch;
12867  // Verboseness is important: it triggers message delivery which can call into
12868  // external code.
12869  try_catch.SetVerbose(true);
12870  CompileRun("throw 'from JS';");
12871  CHECK(try_catch.HasCaught());
12872  CHECK(!CcTest::i_isolate()->has_pending_exception());
12873  CHECK(!CcTest::i_isolate()->has_scheduled_exception());
12874 }
12875 
12876 
12877 static int call_depth;
12878 
12879 
12880 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
12881  TryCatch try_catch;
12882 }
12883 
12884 
12885 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
12886  if (--call_depth) CompileRun("throw 'ThrowInJS';");
12887 }
12888 
12889 
12890 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
12891  if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
12892 }
12893 
12894 
12895 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
12896  Handle<String> errorMessageString = message->Get();
12897  CHECK(!errorMessageString.IsEmpty());
12898  message->GetStackTrace();
12899  message->GetScriptResourceName();
12900 }
12901 
12902 
12903 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
12904  LocalContext context;
12905  v8::Isolate* isolate = context->GetIsolate();
12906  HandleScope scope(isolate);
12907 
12908  Local<Function> func =
12909  FunctionTemplate::New(isolate,
12910  ThrowingCallbackWithTryCatch)->GetFunction();
12911  context->Global()->Set(v8_str("func"), func);
12912 
12913  MessageCallback callbacks[] =
12914  { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
12915  for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
12916  MessageCallback callback = callbacks[i];
12917  if (callback != NULL) {
12918  V8::AddMessageListener(callback);
12919  }
12920  // Some small number to control number of times message handler should
12921  // throw an exception.
12922  call_depth = 5;
12923  ExpectFalse(
12924  "var thrown = false;\n"
12925  "try { func(); } catch(e) { thrown = true; }\n"
12926  "thrown\n");
12927  if (callback != NULL) {
12928  V8::RemoveMessageListeners(callback);
12929  }
12930  }
12931 }
12932 
12933 
12934 static void ParentGetter(Local<String> name,
12937  info.GetReturnValue().Set(v8_num(1));
12938 }
12939 
12940 
12941 static void ChildGetter(Local<String> name,
12944  info.GetReturnValue().Set(v8_num(42));
12945 }
12946 
12947 
12948 THREADED_TEST(Overriding) {
12949  LocalContext context;
12950  v8::Isolate* isolate = context->GetIsolate();
12951  v8::HandleScope scope(isolate);
12952 
12953  // Parent template.
12954  Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
12955  Local<ObjectTemplate> parent_instance_templ =
12956  parent_templ->InstanceTemplate();
12957  parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
12958 
12959  // Template that inherits from the parent template.
12960  Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
12961  Local<ObjectTemplate> child_instance_templ =
12962  child_templ->InstanceTemplate();
12963  child_templ->Inherit(parent_templ);
12964  // Override 'f'. The child version of 'f' should get called for child
12965  // instances.
12966  child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
12967  // Add 'g' twice. The 'g' added last should get called for instances.
12968  child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
12969  child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
12970 
12971  // Add 'h' as an accessor to the proto template with ReadOnly attributes
12972  // so 'h' can be shadowed on the instance object.
12973  Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
12974  child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
12976 
12977  // Add 'i' as an accessor to the instance template with ReadOnly attributes
12978  // but the attribute does not have effect because it is duplicated with
12979  // NULL setter.
12980  child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
12982 
12983 
12984 
12985  // Instantiate the child template.
12986  Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
12987 
12988  // Check that the child function overrides the parent one.
12989  context->Global()->Set(v8_str("o"), instance);
12990  Local<Value> value = v8_compile("o.f")->Run();
12991  // Check that the 'g' that was added last is hit.
12992  CHECK_EQ(42, value->Int32Value());
12993  value = v8_compile("o.g")->Run();
12994  CHECK_EQ(42, value->Int32Value());
12995 
12996  // Check that 'h' cannot be shadowed.
12997  value = v8_compile("o.h = 3; o.h")->Run();
12998  CHECK_EQ(1, value->Int32Value());
12999 
13000  // Check that 'i' cannot be shadowed or changed.
13001  value = v8_compile("o.i = 3; o.i")->Run();
13002  CHECK_EQ(42, value->Int32Value());
13003 }
13004 
13005 
13006 static void IsConstructHandler(
13009  args.GetReturnValue().Set(args.IsConstructCall());
13010 }
13011 
13012 
13013 THREADED_TEST(IsConstructCall) {
13014  v8::Isolate* isolate = CcTest::isolate();
13015  v8::HandleScope scope(isolate);
13016 
13017  // Function template with call handler.
13018  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13019  templ->SetCallHandler(IsConstructHandler);
13020 
13021  LocalContext context;
13022 
13023  context->Global()->Set(v8_str("f"), templ->GetFunction());
13024  Local<Value> value = v8_compile("f()")->Run();
13025  CHECK(!value->BooleanValue());
13026  value = v8_compile("new f()")->Run();
13027  CHECK(value->BooleanValue());
13028 }
13029 
13030 
13031 THREADED_TEST(ObjectProtoToString) {
13032  v8::Isolate* isolate = CcTest::isolate();
13033  v8::HandleScope scope(isolate);
13034  Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
13035  templ->SetClassName(v8_str("MyClass"));
13036 
13037  LocalContext context;
13038 
13039  Local<String> customized_tostring = v8_str("customized toString");
13040 
13041  // Replace Object.prototype.toString
13042  v8_compile("Object.prototype.toString = function() {"
13043  " return 'customized toString';"
13044  "}")->Run();
13045 
13046  // Normal ToString call should call replaced Object.prototype.toString
13047  Local<v8::Object> instance = templ->GetFunction()->NewInstance();
13048  Local<String> value = instance->ToString();
13049  CHECK(value->IsString() && value->Equals(customized_tostring));
13050 
13051  // ObjectProtoToString should not call replace toString function.
13052  value = instance->ObjectProtoToString();
13053  CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
13054 
13055  // Check global
13056  value = context->Global()->ObjectProtoToString();
13057  CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
13058 
13059  // Check ordinary object
13060  Local<Value> object = v8_compile("new Object()")->Run();
13061  value = object.As<v8::Object>()->ObjectProtoToString();
13062  CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
13063 }
13064 
13065 
13066 THREADED_TEST(ObjectGetConstructorName) {
13067  LocalContext context;
13068  v8::HandleScope scope(context->GetIsolate());
13069  v8_compile("function Parent() {};"
13070  "function Child() {};"
13071  "Child.prototype = new Parent();"
13072  "var outer = { inner: function() { } };"
13073  "var p = new Parent();"
13074  "var c = new Child();"
13075  "var x = new outer.inner();")->Run();
13076 
13077  Local<v8::Value> p = context->Global()->Get(v8_str("p"));
13078  CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
13079  v8_str("Parent")));
13080 
13081  Local<v8::Value> c = context->Global()->Get(v8_str("c"));
13082  CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
13083  v8_str("Child")));
13084 
13085  Local<v8::Value> x = context->Global()->Get(v8_str("x"));
13086  CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
13087  v8_str("outer.inner")));
13088 }
13089 
13090 
13091 bool ApiTestFuzzer::fuzzing_ = false;
13092 i::Semaphore ApiTestFuzzer::all_tests_done_(0);
13093 int ApiTestFuzzer::active_tests_;
13094 int ApiTestFuzzer::tests_being_run_;
13095 int ApiTestFuzzer::current_;
13096 
13097 
13098 // We are in a callback and want to switch to another thread (if we
13099 // are currently running the thread fuzzing test).
13101  if (!fuzzing_) return;
13102  ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
13103  test->ContextSwitch();
13104 }
13105 
13106 
13107 // Let the next thread go. Since it is also waiting on the V8 lock it may
13108 // not start immediately.
13109 bool ApiTestFuzzer::NextThread() {
13110  int test_position = GetNextTestNumber();
13111  const char* test_name = RegisterThreadedTest::nth(current_)->name();
13112  if (test_position == current_) {
13113  if (kLogThreading)
13114  printf("Stay with %s\n", test_name);
13115  return false;
13116  }
13117  if (kLogThreading) {
13118  printf("Switch from %s to %s\n",
13119  test_name,
13120  RegisterThreadedTest::nth(test_position)->name());
13121  }
13122  current_ = test_position;
13123  RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
13124  return true;
13125 }
13126 
13127 
13129  // When it is our turn...
13130  gate_.Wait();
13131  {
13132  // ... get the V8 lock and start running the test.
13133  v8::Locker locker(CcTest::isolate());
13134  CallTest();
13135  }
13136  // This test finished.
13137  active_ = false;
13138  active_tests_--;
13139  // If it was the last then signal that fact.
13140  if (active_tests_ == 0) {
13141  all_tests_done_.Signal();
13142  } else {
13143  // Otherwise select a new test and start that.
13144  NextThread();
13145  }
13146 }
13147 
13148 
13149 static unsigned linear_congruential_generator;
13150 
13151 
13153  linear_congruential_generator = i::FLAG_testing_prng_seed;
13154  fuzzing_ = true;
13155  int count = RegisterThreadedTest::count();
13156  int start = count * part / (LAST_PART + 1);
13157  int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
13158  active_tests_ = tests_being_run_ = end - start + 1;
13159  for (int i = 0; i < tests_being_run_; i++) {
13160  RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
13161  }
13162  for (int i = 0; i < active_tests_; i++) {
13164  }
13165 }
13166 
13167 
13168 static void CallTestNumber(int test_number) {
13169  (RegisterThreadedTest::nth(test_number)->callback())();
13170 }
13171 
13172 
13174  // Set off the first test.
13175  current_ = -1;
13176  NextThread();
13177  // Wait till they are all done.
13178  all_tests_done_.Wait();
13179 }
13180 
13181 
13182 int ApiTestFuzzer::GetNextTestNumber() {
13183  int next_test;
13184  do {
13185  next_test = (linear_congruential_generator >> 16) % tests_being_run_;
13186  linear_congruential_generator *= 1664525u;
13187  linear_congruential_generator += 1013904223u;
13188  } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
13189  return next_test;
13190 }
13191 
13192 
13193 void ApiTestFuzzer::ContextSwitch() {
13194  // If the new thread is the same as the current thread there is nothing to do.
13195  if (NextThread()) {
13196  // Now it can start.
13197  v8::Unlocker unlocker(CcTest::isolate());
13198  // Wait till someone starts us again.
13199  gate_.Wait();
13200  // And we're off.
13201  }
13202 }
13203 
13204 
13206  fuzzing_ = false;
13207  for (int i = 0; i < RegisterThreadedTest::count(); i++) {
13209  if (fuzzer != NULL) fuzzer->Join();
13210  }
13211 }
13212 
13213 
13214 // Lets not be needlessly self-referential.
13215 TEST(Threading1) {
13219 }
13220 
13221 
13222 TEST(Threading2) {
13226 }
13227 
13228 
13229 TEST(Threading3) {
13233 }
13234 
13235 
13236 TEST(Threading4) {
13240 }
13241 
13242 
13245  if (kLogThreading)
13246  printf("Start test %d\n", test_number_);
13247  CallTestNumber(test_number_);
13248  if (kLogThreading)
13249  printf("End test %d\n", test_number_);
13250 }
13251 
13252 
13253 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
13254  v8::Isolate* isolate = args.GetIsolate();
13255  CHECK(v8::Locker::IsLocked(isolate));
13257  v8::Unlocker unlocker(isolate);
13258  const char* code = "throw 7;";
13259  {
13260  v8::Locker nested_locker(isolate);
13261  v8::HandleScope scope(isolate);
13262  v8::Handle<Value> exception;
13263  { v8::TryCatch try_catch;
13264  v8::Handle<Value> value = CompileRun(code);
13265  CHECK(value.IsEmpty());
13266  CHECK(try_catch.HasCaught());
13267  // Make sure to wrap the exception in a new handle because
13268  // the handle returned from the TryCatch is destroyed
13269  // when the TryCatch is destroyed.
13270  exception = Local<Value>::New(isolate, try_catch.Exception());
13271  }
13272  args.GetIsolate()->ThrowException(exception);
13273  }
13274 }
13275 
13276 
13277 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
13280  v8::Unlocker unlocker(CcTest::isolate());
13281  const char* code = "throw 7;";
13282  {
13283  v8::Locker nested_locker(CcTest::isolate());
13284  v8::HandleScope scope(args.GetIsolate());
13285  v8::Handle<Value> value = CompileRun(code);
13286  CHECK(value.IsEmpty());
13287  args.GetReturnValue().Set(v8_str("foo"));
13288  }
13289 }
13290 
13291 
13292 // These are locking tests that don't need to be run again
13293 // as part of the locking aggregation tests.
13294 TEST(NestedLockers) {
13295  v8::Isolate* isolate = CcTest::isolate();
13296  v8::Locker locker(isolate);
13297  CHECK(v8::Locker::IsLocked(isolate));
13298  LocalContext env;
13299  v8::HandleScope scope(env->GetIsolate());
13300  Local<v8::FunctionTemplate> fun_templ =
13301  v8::FunctionTemplate::New(isolate, ThrowInJS);
13302  Local<Function> fun = fun_templ->GetFunction();
13303  env->Global()->Set(v8_str("throw_in_js"), fun);
13304  Local<Script> script = v8_compile("(function () {"
13305  " try {"
13306  " throw_in_js();"
13307  " return 42;"
13308  " } catch (e) {"
13309  " return e * 13;"
13310  " }"
13311  "})();");
13312  CHECK_EQ(91, script->Run()->Int32Value());
13313 }
13314 
13315 
13316 // These are locking tests that don't need to be run again
13317 // as part of the locking aggregation tests.
13318 TEST(NestedLockersNoTryCatch) {
13319  v8::Locker locker(CcTest::isolate());
13320  LocalContext env;
13321  v8::HandleScope scope(env->GetIsolate());
13322  Local<v8::FunctionTemplate> fun_templ =
13323  v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
13324  Local<Function> fun = fun_templ->GetFunction();
13325  env->Global()->Set(v8_str("throw_in_js"), fun);
13326  Local<Script> script = v8_compile("(function () {"
13327  " try {"
13328  " throw_in_js();"
13329  " return 42;"
13330  " } catch (e) {"
13331  " return e * 13;"
13332  " }"
13333  "})();");
13334  CHECK_EQ(91, script->Run()->Int32Value());
13335 }
13336 
13337 
13338 THREADED_TEST(RecursiveLocking) {
13339  v8::Locker locker(CcTest::isolate());
13340  {
13341  v8::Locker locker2(CcTest::isolate());
13343  }
13344 }
13345 
13346 
13347 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
13349  v8::Unlocker unlocker(CcTest::isolate());
13350 }
13351 
13352 
13353 THREADED_TEST(LockUnlockLock) {
13354  {
13355  v8::Locker locker(CcTest::isolate());
13357  LocalContext env;
13358  Local<v8::FunctionTemplate> fun_templ =
13359  v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
13360  Local<Function> fun = fun_templ->GetFunction();
13361  env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13362  Local<Script> script = v8_compile("(function () {"
13363  " unlock_for_a_moment();"
13364  " return 42;"
13365  "})();");
13366  CHECK_EQ(42, script->Run()->Int32Value());
13367  }
13368  {
13369  v8::Locker locker(CcTest::isolate());
13371  LocalContext env;
13372  Local<v8::FunctionTemplate> fun_templ =
13373  v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
13374  Local<Function> fun = fun_templ->GetFunction();
13375  env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
13376  Local<Script> script = v8_compile("(function () {"
13377  " unlock_for_a_moment();"
13378  " return 42;"
13379  "})();");
13380  CHECK_EQ(42, script->Run()->Int32Value());
13381  }
13382 }
13383 
13384 
13385 static int GetGlobalObjectsCount() {
13387  int count = 0;
13388  i::HeapIterator it(CcTest::heap());
13389  for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
13390  if (object->IsJSGlobalObject()) count++;
13391  return count;
13392 }
13393 
13394 
13395 static void CheckSurvivingGlobalObjectsCount(int expected) {
13396  // We need to collect all garbage twice to be sure that everything
13397  // has been collected. This is because inline caches are cleared in
13398  // the first garbage collection but some of the maps have already
13399  // been marked at that point. Therefore some of the maps are not
13400  // collected until the second garbage collection.
13403  int count = GetGlobalObjectsCount();
13404 #ifdef DEBUG
13405  if (count != expected) CcTest::heap()->TracePathToGlobal();
13406 #endif
13407  CHECK_EQ(expected, count);
13408 }
13409 
13410 
13411 TEST(DontLeakGlobalObjects) {
13412  // Regression test for issues 1139850 and 1174891.
13413 
13414  i::FLAG_expose_gc = true;
13416 
13417  for (int i = 0; i < 5; i++) {
13418  { v8::HandleScope scope(CcTest::isolate());
13419  LocalContext context;
13420  }
13422  CheckSurvivingGlobalObjectsCount(0);
13423 
13424  { v8::HandleScope scope(CcTest::isolate());
13425  LocalContext context;
13426  v8_compile("Date")->Run();
13427  }
13429  CheckSurvivingGlobalObjectsCount(0);
13430 
13431  { v8::HandleScope scope(CcTest::isolate());
13432  LocalContext context;
13433  v8_compile("/aaa/")->Run();
13434  }
13436  CheckSurvivingGlobalObjectsCount(0);
13437 
13438  { v8::HandleScope scope(CcTest::isolate());
13439  const char* extension_list[] = { "v8/gc" };
13440  v8::ExtensionConfiguration extensions(1, extension_list);
13441  LocalContext context(&extensions);
13442  v8_compile("gc();")->Run();
13443  }
13445  CheckSurvivingGlobalObjectsCount(0);
13446  }
13447 }
13448 
13449 
13450 TEST(CopyablePersistent) {
13451  LocalContext context;
13452  v8::Isolate* isolate = context->GetIsolate();
13453  i::GlobalHandles* globals =
13454  reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13455  int initial_handles = globals->global_handles_count();
13457  CopyableObject;
13458  {
13459  CopyableObject handle1;
13460  {
13461  v8::HandleScope scope(isolate);
13462  handle1.Reset(isolate, v8::Object::New(isolate));
13463  }
13464  CHECK_EQ(initial_handles + 1, globals->global_handles_count());
13465  CopyableObject handle2;
13466  handle2 = handle1;
13467  CHECK(handle1 == handle2);
13468  CHECK_EQ(initial_handles + 2, globals->global_handles_count());
13469  CopyableObject handle3(handle2);
13470  CHECK(handle1 == handle3);
13471  CHECK_EQ(initial_handles + 3, globals->global_handles_count());
13472  }
13473  // Verify autodispose
13474  CHECK_EQ(initial_handles, globals->global_handles_count());
13475 }
13476 
13477 
13478 static void WeakApiCallback(
13479  const v8::WeakCallbackData<v8::Object, Persistent<v8::Object> >& data) {
13480  Local<Value> value = data.GetValue()->Get(v8_str("key"));
13481  CHECK_EQ(231, static_cast<int32_t>(Local<v8::Integer>::Cast(value)->Value()));
13482  data.GetParameter()->Reset();
13483  delete data.GetParameter();
13484 }
13485 
13486 
13487 TEST(WeakCallbackApi) {
13488  LocalContext context;
13489  v8::Isolate* isolate = context->GetIsolate();
13490  i::GlobalHandles* globals =
13491  reinterpret_cast<i::Isolate*>(isolate)->global_handles();
13492  int initial_handles = globals->global_handles_count();
13493  {
13494  v8::HandleScope scope(isolate);
13495  v8::Local<v8::Object> obj = v8::Object::New(isolate);
13496  obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
13498  new v8::Persistent<v8::Object>(isolate, obj);
13500  WeakApiCallback);
13501  }
13502  reinterpret_cast<i::Isolate*>(isolate)->heap()->
13503  CollectAllGarbage(i::Heap::kNoGCFlags);
13504  // Verify disposed.
13505  CHECK_EQ(initial_handles, globals->global_handles_count());
13506 }
13507 
13508 
13511 
13514  v8::HandleScope scope(data.GetIsolate());
13515  bad_handle.Reset(data.GetIsolate(), some_object);
13516  data.GetParameter()->Reset();
13517 }
13518 
13519 
13520 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
13521  LocalContext context;
13522  v8::Isolate* isolate = context->GetIsolate();
13523 
13524  v8::Persistent<v8::Object> handle1, handle2;
13525  {
13526  v8::HandleScope scope(isolate);
13527  some_object.Reset(isolate, v8::Object::New(isolate));
13528  handle1.Reset(isolate, v8::Object::New(isolate));
13529  handle2.Reset(isolate, v8::Object::New(isolate));
13530  }
13531  // Note: order is implementation dependent alas: currently
13532  // global handle nodes are processed by PostGarbageCollectionProcessing
13533  // in reverse allocation order, so if second allocated handle is deleted,
13534  // weak callback of the first handle would be able to 'reallocate' it.
13535  handle1.SetWeak(&handle1, NewPersistentHandleCallback);
13536  handle2.Reset();
13538 }
13539 
13540 
13542 
13545  to_be_disposed.Reset();
13547  data.GetParameter()->Reset();
13548 }
13549 
13550 
13551 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
13552  LocalContext context;
13553  v8::Isolate* isolate = context->GetIsolate();
13554 
13555  v8::Persistent<v8::Object> handle1, handle2;
13556  {
13557  v8::HandleScope scope(isolate);
13558  handle1.Reset(isolate, v8::Object::New(isolate));
13559  handle2.Reset(isolate, v8::Object::New(isolate));
13560  }
13561  handle1.SetWeak(&handle1, DisposeAndForceGcCallback);
13562  to_be_disposed.Reset(isolate, handle2);
13564 }
13565 
13568  data.GetParameter()->Reset();
13569 }
13570 
13573  v8::HandleScope scope(data.GetIsolate());
13574  v8::Persistent<v8::Object>(data.GetIsolate(),
13575  v8::Object::New(data.GetIsolate()));
13576  data.GetParameter()->Reset();
13577 }
13578 
13579 
13580 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
13581  LocalContext context;
13582  v8::Isolate* isolate = context->GetIsolate();
13583 
13584  v8::Persistent<v8::Object> handle1, handle2, handle3;
13585  {
13586  v8::HandleScope scope(isolate);
13587  handle3.Reset(isolate, v8::Object::New(isolate));
13588  handle2.Reset(isolate, v8::Object::New(isolate));
13589  handle1.Reset(isolate, v8::Object::New(isolate));
13590  }
13591  handle2.SetWeak(&handle2, DisposingCallback);
13592  handle3.SetWeak(&handle3, HandleCreatingCallback);
13594 }
13595 
13596 
13597 THREADED_TEST(CheckForCrossContextObjectLiterals) {
13599 
13600  const int nof = 2;
13601  const char* sources[nof] = {
13602  "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
13603  "Object()"
13604  };
13605 
13606  for (int i = 0; i < nof; i++) {
13607  const char* source = sources[i];
13608  { v8::HandleScope scope(CcTest::isolate());
13609  LocalContext context;
13610  CompileRun(source);
13611  }
13612  { v8::HandleScope scope(CcTest::isolate());
13613  LocalContext context;
13614  CompileRun(source);
13615  }
13616  }
13617 }
13618 
13619 
13620 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
13621  v8::EscapableHandleScope inner(env->GetIsolate());
13622  env->Enter();
13623  v8::Local<Value> three = v8_num(3);
13624  v8::Local<Value> value = inner.Escape(three);
13625  env->Exit();
13626  return value;
13627 }
13628 
13629 
13630 THREADED_TEST(NestedHandleScopeAndContexts) {
13631  v8::Isolate* isolate = CcTest::isolate();
13632  v8::HandleScope outer(isolate);
13633  v8::Local<Context> env = Context::New(isolate);
13634  env->Enter();
13635  v8::Handle<Value> value = NestedScope(env);
13636  v8::Handle<String> str(value->ToString());
13637  CHECK(!str.IsEmpty());
13638  env->Exit();
13639 }
13640 
13641 
13642 static bool MatchPointers(void* key1, void* key2) {
13643  return key1 == key2;
13644 }
13645 
13646 
13647 struct SymbolInfo {
13648  size_t id;
13649  size_t size;
13650  std::string name;
13651 };
13652 
13653 
13655  public:
13657  CHECK(instance_ == NULL);
13658  instance_ = this;
13659  }
13661  CHECK(instance_ == this);
13662  instance_ = NULL;
13663  }
13664  void Reset() {
13665  symbols_.clear();
13666  symbol_locations_.clear();
13667  invocations_.clear();
13668  }
13669  void RunTest();
13670  void OnJitEvent(const v8::JitCodeEvent* event);
13671  static void JitEvent(const v8::JitCodeEvent* event) {
13672  CHECK(instance_ != NULL);
13673  instance_->OnJitEvent(event);
13674  }
13675 
13676  void OnEntryHook(uintptr_t function,
13677  uintptr_t return_addr_location);
13678  static void EntryHook(uintptr_t function,
13679  uintptr_t return_addr_location) {
13680  CHECK(instance_ != NULL);
13681  instance_->OnEntryHook(function, return_addr_location);
13682  }
13683 
13685  CHECK(instance_ != NULL);
13686  args.GetReturnValue().Set(v8_num(42));
13687  }
13688  void RunLoopInNewEnv(v8::Isolate* isolate);
13689 
13690  // Records addr as location of symbol.
13691  void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
13692 
13693  // Finds the symbol containing addr
13695  // Returns the number of invocations where the caller name contains
13696  // \p caller_name and the function name contains \p function_name.
13697  int CountInvocations(const char* caller_name,
13698  const char* function_name);
13699 
13702 
13703  typedef std::map<size_t, SymbolInfo> SymbolMap;
13704  typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
13705  typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
13709 
13711 };
13713 
13714 
13715 // Returns true if addr is in the range [start, start+len).
13716 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
13717  if (start <= addr && start + len > addr)
13718  return true;
13719 
13720  return false;
13721 }
13722 
13724  SymbolInfo* symbol) {
13725  // Insert the symbol at the new location.
13726  SymbolLocationMap::iterator it =
13727  symbol_locations_.insert(std::make_pair(addr, symbol)).first;
13728  // Now erase symbols to the left and right that overlap this one.
13729  while (it != symbol_locations_.begin()) {
13730  SymbolLocationMap::iterator left = it;
13731  --left;
13732  if (!Overlaps(left->first, left->second->size, addr))
13733  break;
13734  symbol_locations_.erase(left);
13735  }
13736 
13737  // Now erase symbols to the left and right that overlap this one.
13738  while (true) {
13739  SymbolLocationMap::iterator right = it;
13740  ++right;
13741  if (right == symbol_locations_.end())
13742  break;
13743  if (!Overlaps(addr, symbol->size, right->first))
13744  break;
13745  symbol_locations_.erase(right);
13746  }
13747 }
13748 
13749 
13751  switch (event->type) {
13753  CHECK(event->code_start != NULL);
13754  CHECK_NE(0, static_cast<int>(event->code_len));
13755  CHECK(event->name.str != NULL);
13756  size_t symbol_id = symbols_.size();
13757 
13758  // Record the new symbol.
13759  SymbolInfo& info = symbols_[symbol_id];
13760  info.id = symbol_id;
13761  info.size = event->code_len;
13762  info.name.assign(event->name.str, event->name.str + event->name.len);
13763 
13764  // And record it's location.
13765  InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
13766  }
13767  break;
13768 
13770  // We would like to never see code move that we haven't seen before,
13771  // but the code creation event does not happen until the line endings
13772  // have been calculated (this is so that we can report the line in the
13773  // script at which the function source is found, see
13774  // Compiler::RecordFunctionCompilation) and the line endings
13775  // calculations can cause a GC, which can move the newly created code
13776  // before its existence can be logged.
13777  SymbolLocationMap::iterator it(
13778  symbol_locations_.find(
13779  reinterpret_cast<i::Address>(event->code_start)));
13780  if (it != symbol_locations_.end()) {
13781  // Found a symbol at this location, move it.
13782  SymbolInfo* info = it->second;
13783  symbol_locations_.erase(it);
13784  InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
13785  info);
13786  }
13787  }
13788  default:
13789  break;
13790  }
13791 }
13792 
13794  uintptr_t function, uintptr_t return_addr_location) {
13795  // Get the function's code object.
13796  i::Code* function_code = i::Code::GetCodeFromTargetAddress(
13797  reinterpret_cast<i::Address>(function));
13798  CHECK(function_code != NULL);
13799 
13800  // Then try and look up the caller's code object.
13801  i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
13802 
13803  // Count the invocation.
13804  SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
13805  SymbolInfo* function_symbol =
13806  FindSymbolForAddr(reinterpret_cast<i::Address>(function));
13807  ++invocations_[std::make_pair(caller_symbol, function_symbol)];
13808 
13809  if (!bar_func_.is_null() && function_code == bar_func_->code()) {
13810  // Check that we have a symbol for the "bar" function at the right location.
13811  SymbolLocationMap::iterator it(
13812  symbol_locations_.find(function_code->instruction_start()));
13813  CHECK(it != symbol_locations_.end());
13814  }
13815 
13816  if (!foo_func_.is_null() && function_code == foo_func_->code()) {
13817  // Check that we have a symbol for "foo" at the right location.
13818  SymbolLocationMap::iterator it(
13819  symbol_locations_.find(function_code->instruction_start()));
13820  CHECK(it != symbol_locations_.end());
13821  }
13822 }
13823 
13824 
13826  SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
13827  // Do we have a direct hit on a symbol?
13828  if (it != symbol_locations_.end()) {
13829  if (it->first == addr)
13830  return it->second;
13831  }
13832 
13833  // If not a direct hit, it'll have to be the previous symbol.
13834  if (it == symbol_locations_.begin())
13835  return NULL;
13836 
13837  --it;
13838  size_t offs = addr - it->first;
13839  if (offs < it->second->size)
13840  return it->second;
13841 
13842  return NULL;
13843 }
13844 
13845 
13847  const char* caller_name, const char* function_name) {
13848  InvocationMap::iterator it(invocations_.begin());
13849  int invocations = 0;
13850  for (; it != invocations_.end(); ++it) {
13851  SymbolInfo* caller = it->first.first;
13852  SymbolInfo* function = it->first.second;
13853 
13854  // Filter out non-matching functions.
13855  if (function_name != NULL) {
13856  if (function->name.find(function_name) == std::string::npos)
13857  continue;
13858  }
13859 
13860  // Filter out non-matching callers.
13861  if (caller_name != NULL) {
13862  if (caller == NULL)
13863  continue;
13864  if (caller->name.find(caller_name) == std::string::npos)
13865  continue;
13866  }
13867 
13868  // It matches add the invocation count to the tally.
13869  invocations += it->second;
13870  }
13871 
13872  return invocations;
13873 }
13874 
13875 
13877  v8::HandleScope outer(isolate);
13878  v8::Local<Context> env = Context::New(isolate);
13879  env->Enter();
13880 
13881  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
13882  t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
13883  env->Global()->Set(v8_str("obj"), t->NewInstance());
13884 
13885  const char* script =
13886  "function bar() {\n"
13887  " var sum = 0;\n"
13888  " for (i = 0; i < 100; ++i)\n"
13889  " sum = foo(i);\n"
13890  " return sum;\n"
13891  "}\n"
13892  "function foo(i) { return i * i; }\n"
13893  "// Invoke on the runtime function.\n"
13894  "obj.asdf()";
13895  CompileRun(script);
13897  v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
13898  ASSERT(!bar_func_.is_null());
13899 
13900  foo_func_ =
13902  v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
13903  ASSERT(!foo_func_.is_null());
13904 
13905  v8::Handle<v8::Value> value = CompileRun("bar();");
13906  CHECK(value->IsNumber());
13907  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13908 
13909  // Test the optimized codegen path.
13910  value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
13911  "bar();");
13912  CHECK(value->IsNumber());
13913  CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
13914 
13915  env->Exit();
13916 }
13917 
13918 
13920  // Work in a new isolate throughout.
13921  v8::Isolate* isolate = v8::Isolate::New();
13922 
13923  // Test setting the entry hook on the new isolate.
13925 
13926  // Replacing the hook, once set should fail.
13928 
13929  {
13930  v8::Isolate::Scope scope(isolate);
13931 
13933 
13934  RunLoopInNewEnv(isolate);
13935 
13936  // Check the exepected invocation counts.
13937  CHECK_EQ(2, CountInvocations(NULL, "bar"));
13938  CHECK_EQ(200, CountInvocations("bar", "foo"));
13939  CHECK_EQ(200, CountInvocations(NULL, "foo"));
13940 
13941  // Verify that we have an entry hook on some specific stubs.
13942  CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
13943  CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
13944  CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
13945  }
13946  isolate->Dispose();
13947 
13948  Reset();
13949 
13950  // Make sure a second isolate is unaffected by the previous entry hook.
13951  isolate = v8::Isolate::New();
13952  {
13953  v8::Isolate::Scope scope(isolate);
13954 
13955  // Reset the entry count to zero and set the entry hook.
13956  RunLoopInNewEnv(isolate);
13957 
13958  // We should record no invocations in this isolate.
13959  CHECK_EQ(0, static_cast<int>(invocations_.size()));
13960  }
13961  // Since the isolate has been used, we shouldn't be able to set an entry
13962  // hook anymore.
13964 
13965  isolate->Dispose();
13966 }
13967 
13968 
13969 TEST(SetFunctionEntryHook) {
13970  // FunctionEntryHook does not work well with experimental natives.
13971  // Experimental natives are compiled during snapshot deserialization.
13972  // This test breaks because InstallGetter (function from snapshot that
13973  // only gets called from experimental natives) is compiled with entry hooks.
13974  i::FLAG_allow_natives_syntax = true;
13975  i::FLAG_use_inlining = false;
13976 
13978  test.RunTest();
13979 }
13980 
13981 
13982 static i::HashMap* code_map = NULL;
13983 static i::HashMap* jitcode_line_info = NULL;
13984 static int saw_bar = 0;
13985 static int move_events = 0;
13986 
13987 
13988 static bool FunctionNameIs(const char* expected,
13989  const v8::JitCodeEvent* event) {
13990  // Log lines for functions are of the general form:
13991  // "LazyCompile:<type><function_name>", where the type is one of
13992  // "*", "~" or "".
13993  static const char kPreamble[] = "LazyCompile:";
13994  static size_t kPreambleLen = sizeof(kPreamble) - 1;
13995 
13996  if (event->name.len < sizeof(kPreamble) - 1 ||
13997  strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
13998  return false;
13999  }
14000 
14001  const char* tail = event->name.str + kPreambleLen;
14002  size_t tail_len = event->name.len - kPreambleLen;
14003  size_t expected_len = strlen(expected);
14004  if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
14005  --tail_len;
14006  ++tail;
14007  }
14008 
14009  // Check for tails like 'bar :1'.
14010  if (tail_len > expected_len + 2 &&
14011  tail[expected_len] == ' ' &&
14012  tail[expected_len + 1] == ':' &&
14013  tail[expected_len + 2] &&
14014  !strncmp(tail, expected, expected_len)) {
14015  return true;
14016  }
14017 
14018  if (tail_len != expected_len)
14019  return false;
14020 
14021  return strncmp(tail, expected, expected_len) == 0;
14022 }
14023 
14024 
14025 static void event_handler(const v8::JitCodeEvent* event) {
14026  CHECK(event != NULL);
14027  CHECK(code_map != NULL);
14028  CHECK(jitcode_line_info != NULL);
14029 
14030  class DummyJitCodeLineInfo {
14031  };
14032 
14033  switch (event->type) {
14035  CHECK(event->code_start != NULL);
14036  CHECK_NE(0, static_cast<int>(event->code_len));
14037  CHECK(event->name.str != NULL);
14038  i::HashMap::Entry* entry =
14039  code_map->Lookup(event->code_start,
14041  true);
14042  entry->value = reinterpret_cast<void*>(event->code_len);
14043 
14044  if (FunctionNameIs("bar", event)) {
14045  ++saw_bar;
14046  }
14047  }
14048  break;
14049 
14051  uint32_t hash = i::ComputePointerHash(event->code_start);
14052  // We would like to never see code move that we haven't seen before,
14053  // but the code creation event does not happen until the line endings
14054  // have been calculated (this is so that we can report the line in the
14055  // script at which the function source is found, see
14056  // Compiler::RecordFunctionCompilation) and the line endings
14057  // calculations can cause a GC, which can move the newly created code
14058  // before its existence can be logged.
14059  i::HashMap::Entry* entry =
14060  code_map->Lookup(event->code_start, hash, false);
14061  if (entry != NULL) {
14062  ++move_events;
14063 
14064  CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
14065  code_map->Remove(event->code_start, hash);
14066 
14067  entry = code_map->Lookup(event->new_code_start,
14069  true);
14070  CHECK(entry != NULL);
14071  entry->value = reinterpret_cast<void*>(event->code_len);
14072  }
14073  }
14074  break;
14075 
14077  // Object/code removal events are currently not dispatched from the GC.
14078  CHECK(false);
14079  break;
14080 
14081  // For CODE_START_LINE_INFO_RECORDING event, we will create one
14082  // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
14083  // record it in jitcode_line_info.
14085  DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
14086  v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
14087  temp_event->user_data = line_info;
14088  i::HashMap::Entry* entry =
14089  jitcode_line_info->Lookup(line_info,
14090  i::ComputePointerHash(line_info),
14091  true);
14092  entry->value = reinterpret_cast<void*>(line_info);
14093  }
14094  break;
14095  // For these two events, we will check whether the event->user_data
14096  // data structure is created before during CODE_START_LINE_INFO_RECORDING
14097  // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
14099  CHECK(event->user_data != NULL);
14100  uint32_t hash = i::ComputePointerHash(event->user_data);
14101  i::HashMap::Entry* entry =
14102  jitcode_line_info->Lookup(event->user_data, hash, false);
14103  CHECK(entry != NULL);
14104  delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
14105  }
14106  break;
14107 
14109  CHECK(event->user_data != NULL);
14110  uint32_t hash = i::ComputePointerHash(event->user_data);
14111  i::HashMap::Entry* entry =
14112  jitcode_line_info->Lookup(event->user_data, hash, false);
14113  CHECK(entry != NULL);
14114  }
14115  break;
14116 
14117  default:
14118  // Impossible event.
14119  CHECK(false);
14120  break;
14121  }
14122 }
14123 
14124 
14125 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
14126  i::FLAG_stress_compaction = true;
14127  i::FLAG_incremental_marking = false;
14128  const char* script =
14129  "function bar() {"
14130  " var sum = 0;"
14131  " for (i = 0; i < 100; ++i)"
14132  " sum = foo(i);"
14133  " return sum;"
14134  "}"
14135  "function foo(i) { return i * i; };"
14136  "bar();";
14137 
14138  // Run this test in a new isolate to make sure we don't
14139  // have remnants of state from other code.
14140  v8::Isolate* isolate = v8::Isolate::New();
14141  isolate->Enter();
14142  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
14143  i::Heap* heap = i_isolate->heap();
14144 
14145  {
14146  v8::HandleScope scope(isolate);
14147  i::HashMap code(MatchPointers);
14148  code_map = &code;
14149 
14150  i::HashMap lineinfo(MatchPointers);
14151  jitcode_line_info = &lineinfo;
14152 
14153  saw_bar = 0;
14154  move_events = 0;
14155 
14156  V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
14157 
14158  // Generate new code objects sparsely distributed across several
14159  // different fragmented code-space pages.
14160  const int kIterations = 10;
14161  for (int i = 0; i < kIterations; ++i) {
14162  LocalContext env(isolate);
14163  i::AlwaysAllocateScope always_allocate(i_isolate);
14164  SimulateFullSpace(heap->code_space());
14165  CompileRun(script);
14166 
14167  // Keep a strong reference to the code object in the handle scope.
14169  v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
14171  v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
14172 
14173  // Clear the compilation cache to get more wastage.
14174  reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
14175  }
14176 
14177  // Force code movement.
14178  heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler");
14179 
14180  V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14181 
14182  CHECK_LE(kIterations, saw_bar);
14183  CHECK_LT(0, move_events);
14184 
14185  code_map = NULL;
14186  jitcode_line_info = NULL;
14187  }
14188 
14189  isolate->Exit();
14190  isolate->Dispose();
14191 
14192  // Do this in a new isolate.
14193  isolate = v8::Isolate::New();
14194  isolate->Enter();
14195 
14196  // Verify that we get callbacks for existing code objects when we
14197  // request enumeration of existing code.
14198  {
14199  v8::HandleScope scope(isolate);
14200  LocalContext env(isolate);
14201  CompileRun(script);
14202 
14203  // Now get code through initial iteration.
14204  i::HashMap code(MatchPointers);
14205  code_map = &code;
14206 
14207  i::HashMap lineinfo(MatchPointers);
14208  jitcode_line_info = &lineinfo;
14209 
14210  V8::SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting, event_handler);
14211  V8::SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
14212 
14213  jitcode_line_info = NULL;
14214  // We expect that we got some events. Note that if we could get code removal
14215  // notifications, we could compare two collections, one created by listening
14216  // from the time of creation of an isolate, and the other by subscribing
14217  // with EnumExisting.
14218  CHECK_LT(0, code.occupancy());
14219 
14220  code_map = NULL;
14221  }
14222 
14223  isolate->Exit();
14224  isolate->Dispose();
14225 }
14226 
14227 
14228 THREADED_TEST(ExternalAllocatedMemory) {
14229  v8::Isolate* isolate = CcTest::isolate();
14230  v8::HandleScope outer(isolate);
14231  v8::Local<Context> env(Context::New(isolate));
14232  CHECK(!env.IsEmpty());
14233  const int64_t kSize = 1024*1024;
14234  int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
14235  CHECK_EQ(baseline + kSize,
14236  isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
14237  CHECK_EQ(baseline,
14238  isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
14239 }
14240 
14241 
14242 // Regression test for issue 54, object templates with internal fields
14243 // but no accessors or interceptors did not get their internal field
14244 // count set on instances.
14245 THREADED_TEST(Regress54) {
14246  LocalContext context;
14247  v8::Isolate* isolate = context->GetIsolate();
14248  v8::HandleScope outer(isolate);
14250  if (templ.IsEmpty()) {
14251  v8::EscapableHandleScope inner(isolate);
14253  local->SetInternalFieldCount(1);
14254  templ.Reset(isolate, inner.Escape(local));
14255  }
14256  v8::Handle<v8::Object> result =
14257  v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
14258  CHECK_EQ(1, result->InternalFieldCount());
14259 }
14260 
14261 
14262 // If part of the threaded tests, this test makes ThreadingTest fail
14263 // on mac.
14264 TEST(CatchStackOverflow) {
14265  LocalContext context;
14266  v8::HandleScope scope(context->GetIsolate());
14267  v8::TryCatch try_catch;
14268  v8::Handle<v8::Value> result = CompileRun(
14269  "function f() {"
14270  " return f();"
14271  "}"
14272  ""
14273  "f();");
14274  CHECK(result.IsEmpty());
14275 }
14276 
14277 
14278 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
14279  const char* resource_name,
14280  int line_offset) {
14282  v8::TryCatch try_catch;
14283  v8::Handle<v8::Value> result = script->Run();
14284  CHECK(result.IsEmpty());
14285  CHECK(try_catch.HasCaught());
14286  v8::Handle<v8::Message> message = try_catch.Message();
14287  CHECK(!message.IsEmpty());
14288  CHECK_EQ(10 + line_offset, message->GetLineNumber());
14289  CHECK_EQ(91, message->GetStartPosition());
14290  CHECK_EQ(92, message->GetEndPosition());
14291  CHECK_EQ(2, message->GetStartColumn());
14292  CHECK_EQ(3, message->GetEndColumn());
14293  v8::String::Utf8Value line(message->GetSourceLine());
14294  CHECK_EQ(" throw 'nirk';", *line);
14295  v8::String::Utf8Value name(message->GetScriptResourceName());
14296  CHECK_EQ(resource_name, *name);
14297 }
14298 
14299 
14300 THREADED_TEST(TryCatchSourceInfo) {
14301  LocalContext context;
14302  v8::HandleScope scope(context->GetIsolate());
14303  v8::Local<v8::String> source = v8_str(
14304  "function Foo() {\n"
14305  " return Bar();\n"
14306  "}\n"
14307  "\n"
14308  "function Bar() {\n"
14309  " return Baz();\n"
14310  "}\n"
14311  "\n"
14312  "function Baz() {\n"
14313  " throw 'nirk';\n"
14314  "}\n"
14315  "\n"
14316  "Foo();\n");
14317 
14318  const char* resource_name;
14319  v8::Handle<v8::Script> script;
14320  resource_name = "test.js";
14321  script = CompileWithOrigin(source, resource_name);
14322  CheckTryCatchSourceInfo(script, resource_name, 0);
14323 
14324  resource_name = "test1.js";
14325  v8::ScriptOrigin origin1(
14326  v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
14327  script = v8::Script::Compile(source, &origin1);
14328  CheckTryCatchSourceInfo(script, resource_name, 0);
14329 
14330  resource_name = "test2.js";
14331  v8::ScriptOrigin origin2(
14332  v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
14333  v8::Integer::New(context->GetIsolate(), 7));
14334  script = v8::Script::Compile(source, &origin2);
14335  CheckTryCatchSourceInfo(script, resource_name, 7);
14336 }
14337 
14338 
14339 THREADED_TEST(CompilationCache) {
14340  LocalContext context;
14341  v8::HandleScope scope(context->GetIsolate());
14342  v8::Handle<v8::String> source0 =
14343  v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14344  v8::Handle<v8::String> source1 =
14345  v8::String::NewFromUtf8(context->GetIsolate(), "1234");
14346  v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
14347  v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
14348  v8::Handle<v8::Script> script2 =
14349  v8::Script::Compile(source0); // different origin
14350  CHECK_EQ(1234, script0->Run()->Int32Value());
14351  CHECK_EQ(1234, script1->Run()->Int32Value());
14352  CHECK_EQ(1234, script2->Run()->Int32Value());
14353 }
14354 
14355 
14356 static void FunctionNameCallback(
14359  args.GetReturnValue().Set(v8_num(42));
14360 }
14361 
14362 
14363 THREADED_TEST(CallbackFunctionName) {
14364  LocalContext context;
14365  v8::Isolate* isolate = context->GetIsolate();
14366  v8::HandleScope scope(isolate);
14367  Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
14368  t->Set(v8_str("asdf"),
14369  v8::FunctionTemplate::New(isolate, FunctionNameCallback));
14370  context->Global()->Set(v8_str("obj"), t->NewInstance());
14371  v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
14372  CHECK(value->IsString());
14373  v8::String::Utf8Value name(value);
14374  CHECK_EQ("asdf", *name);
14375 }
14376 
14377 
14378 THREADED_TEST(DateAccess) {
14379  LocalContext context;
14380  v8::HandleScope scope(context->GetIsolate());
14381  v8::Handle<v8::Value> date =
14382  v8::Date::New(context->GetIsolate(), 1224744689038.0);
14383  CHECK(date->IsDate());
14384  CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
14385 }
14386 
14387 
14390  int elmc,
14391  const char* elmv[]) {
14392  v8::Handle<v8::Object> obj = val.As<v8::Object>();
14393  v8::Handle<v8::Array> props = obj->GetPropertyNames();
14394  CHECK_EQ(elmc, props->Length());
14395  for (int i = 0; i < elmc; i++) {
14396  v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
14397  CHECK_EQ(elmv[i], *elm);
14398  }
14399 }
14400 
14401 
14404  int elmc,
14405  const char* elmv[]) {
14406  v8::Handle<v8::Object> obj = val.As<v8::Object>();
14408  CHECK_EQ(elmc, props->Length());
14409  for (int i = 0; i < elmc; i++) {
14410  v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
14411  CHECK_EQ(elmv[i], *elm);
14412  }
14413 }
14414 
14415 
14416 THREADED_TEST(PropertyEnumeration) {
14417  LocalContext context;
14418  v8::Isolate* isolate = context->GetIsolate();
14419  v8::HandleScope scope(isolate);
14420  v8::Handle<v8::Value> obj = CompileRun(
14421  "var result = [];"
14422  "result[0] = {};"
14423  "result[1] = {a: 1, b: 2};"
14424  "result[2] = [1, 2, 3];"
14425  "var proto = {x: 1, y: 2, z: 3};"
14426  "var x = { __proto__: proto, w: 0, z: 1 };"
14427  "result[3] = x;"
14428  "result;");
14429  v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14430  CHECK_EQ(4, elms->Length());
14431  int elmc0 = 0;
14432  const char** elmv0 = NULL;
14434  isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14436  isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14437  int elmc1 = 2;
14438  const char* elmv1[] = {"a", "b"};
14440  isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14442  isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
14443  int elmc2 = 3;
14444  const char* elmv2[] = {"0", "1", "2"};
14446  isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14448  isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
14449  int elmc3 = 4;
14450  const char* elmv3[] = {"w", "z", "x", "y"};
14452  isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
14453  int elmc4 = 2;
14454  const char* elmv4[] = {"w", "z"};
14456  isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
14457 }
14458 
14459 
14460 THREADED_TEST(PropertyEnumeration2) {
14461  LocalContext context;
14462  v8::Isolate* isolate = context->GetIsolate();
14463  v8::HandleScope scope(isolate);
14464  v8::Handle<v8::Value> obj = CompileRun(
14465  "var result = [];"
14466  "result[0] = {};"
14467  "result[1] = {a: 1, b: 2};"
14468  "result[2] = [1, 2, 3];"
14469  "var proto = {x: 1, y: 2, z: 3};"
14470  "var x = { __proto__: proto, w: 0, z: 1 };"
14471  "result[3] = x;"
14472  "result;");
14473  v8::Handle<v8::Array> elms = obj.As<v8::Array>();
14474  CHECK_EQ(4, elms->Length());
14475  int elmc0 = 0;
14476  const char** elmv0 = NULL;
14477  CheckProperties(isolate,
14478  elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
14479 
14480  v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
14481  v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
14482  CHECK_EQ(0, props->Length());
14483  for (uint32_t i = 0; i < props->Length(); i++) {
14484  printf("p[%d]\n", i);
14485  }
14486 }
14487 
14488 static bool NamedSetAccessBlocker(Local<v8::Object> obj,
14489  Local<Value> name,
14490  v8::AccessType type,
14491  Local<Value> data) {
14492  return type != v8::ACCESS_SET;
14493 }
14494 
14495 
14496 static bool IndexedSetAccessBlocker(Local<v8::Object> obj,
14497  uint32_t key,
14498  v8::AccessType type,
14499  Local<Value> data) {
14500  return type != v8::ACCESS_SET;
14501 }
14502 
14503 
14504 THREADED_TEST(DisableAccessChecksWhileConfiguring) {
14505  LocalContext context;
14506  v8::Isolate* isolate = context->GetIsolate();
14507  v8::HandleScope scope(isolate);
14508  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
14509  templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14510  IndexedSetAccessBlocker);
14511  templ->Set(v8_str("x"), v8::True(isolate));
14512  Local<v8::Object> instance = templ->NewInstance();
14513  context->Global()->Set(v8_str("obj"), instance);
14514  Local<Value> value = CompileRun("obj.x");
14515  CHECK(value->BooleanValue());
14516 }
14517 
14518 
14519 static bool NamedGetAccessBlocker(Local<v8::Object> obj,
14520  Local<Value> name,
14521  v8::AccessType type,
14522  Local<Value> data) {
14523  return false;
14524 }
14525 
14526 
14527 static bool IndexedGetAccessBlocker(Local<v8::Object> obj,
14528  uint32_t key,
14529  v8::AccessType type,
14530  Local<Value> data) {
14531  return false;
14532 }
14533 
14534 
14535 
14536 THREADED_TEST(AccessChecksReenabledCorrectly) {
14537  LocalContext context;
14538  v8::Isolate* isolate = context->GetIsolate();
14539  v8::HandleScope scope(isolate);
14540  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
14541  templ->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14542  IndexedGetAccessBlocker);
14543  templ->Set(v8_str("a"), v8_str("a"));
14544  // Add more than 8 (see kMaxFastProperties) properties
14545  // so that the constructor will force copying map.
14546  // Cannot sprintf, gcc complains unsafety.
14547  char buf[4];
14548  for (char i = '0'; i <= '9' ; i++) {
14549  buf[0] = i;
14550  for (char j = '0'; j <= '9'; j++) {
14551  buf[1] = j;
14552  for (char k = '0'; k <= '9'; k++) {
14553  buf[2] = k;
14554  buf[3] = 0;
14555  templ->Set(v8_str(buf), v8::Number::New(isolate, k));
14556  }
14557  }
14558  }
14559 
14560  Local<v8::Object> instance_1 = templ->NewInstance();
14561  context->Global()->Set(v8_str("obj_1"), instance_1);
14562 
14563  Local<Value> value_1 = CompileRun("obj_1.a");
14564  CHECK(value_1->IsUndefined());
14565 
14566  Local<v8::Object> instance_2 = templ->NewInstance();
14567  context->Global()->Set(v8_str("obj_2"), instance_2);
14568 
14569  Local<Value> value_2 = CompileRun("obj_2.a");
14570  CHECK(value_2->IsUndefined());
14571 }
14572 
14573 
14574 // This tests that access check information remains on the global
14575 // object template when creating contexts.
14576 THREADED_TEST(AccessControlRepeatedContextCreation) {
14577  v8::Isolate* isolate = CcTest::isolate();
14578  v8::HandleScope handle_scope(isolate);
14579  v8::Handle<v8::ObjectTemplate> global_template =
14580  v8::ObjectTemplate::New(isolate);
14581  global_template->SetAccessCheckCallbacks(NamedSetAccessBlocker,
14582  IndexedSetAccessBlocker);
14583  i::Handle<i::ObjectTemplateInfo> internal_template =
14584  v8::Utils::OpenHandle(*global_template);
14585  CHECK(!internal_template->constructor()->IsUndefined());
14587  i::FunctionTemplateInfo::cast(internal_template->constructor()));
14588  CHECK(!constructor->access_check_info()->IsUndefined());
14589  v8::Local<Context> context0(Context::New(isolate, NULL, global_template));
14590  CHECK(!context0.IsEmpty());
14591  CHECK(!constructor->access_check_info()->IsUndefined());
14592 }
14593 
14594 
14595 THREADED_TEST(TurnOnAccessCheck) {
14596  v8::Isolate* isolate = CcTest::isolate();
14597  v8::HandleScope handle_scope(isolate);
14598 
14599  // Create an environment with access check to the global object disabled by
14600  // default.
14601  v8::Handle<v8::ObjectTemplate> global_template =
14602  v8::ObjectTemplate::New(isolate);
14603  global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
14604  IndexedGetAccessBlocker,
14606  false);
14607  v8::Local<Context> context = Context::New(isolate, NULL, global_template);
14608  Context::Scope context_scope(context);
14609 
14610  // Set up a property and a number of functions.
14611  context->Global()->Set(v8_str("a"), v8_num(1));
14612  CompileRun("function f1() {return a;}"
14613  "function f2() {return a;}"
14614  "function g1() {return h();}"
14615  "function g2() {return h();}"
14616  "function h() {return 1;}");
14617  Local<Function> f1 =
14618  Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14619  Local<Function> f2 =
14620  Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14621  Local<Function> g1 =
14622  Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14623  Local<Function> g2 =
14624  Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14625  Local<Function> h =
14626  Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14627 
14628  // Get the global object.
14629  v8::Handle<v8::Object> global = context->Global();
14630 
14631  // Call f1 one time and f2 a number of times. This will ensure that f1 still
14632  // uses the runtime system to retreive property a whereas f2 uses global load
14633  // inline cache.
14634  CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14635  for (int i = 0; i < 4; i++) {
14636  CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14637  }
14638 
14639  // Same for g1 and g2.
14640  CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14641  for (int i = 0; i < 4; i++) {
14642  CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14643  }
14644 
14645  // Detach the global and turn on access check.
14646  Local<Object> hidden_global = Local<Object>::Cast(
14647  context->Global()->GetPrototype());
14648  context->DetachGlobal();
14649  hidden_global->TurnOnAccessCheck();
14650 
14651  // Failing access check to property get results in undefined.
14652  CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14653  CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14654 
14655  // Failing access check to function call results in exception.
14656  CHECK(g1->Call(global, 0, NULL).IsEmpty());
14657  CHECK(g2->Call(global, 0, NULL).IsEmpty());
14658 
14659  // No failing access check when just returning a constant.
14660  CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14661 }
14662 
14663 
14664 static const char* kPropertyA = "a";
14665 static const char* kPropertyH = "h";
14666 
14667 static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
14668  Local<Value> name,
14669  v8::AccessType type,
14670  Local<Value> data) {
14671  if (!name->IsString()) return false;
14672  i::Handle<i::String> name_handle =
14673  v8::Utils::OpenHandle(String::Cast(*name));
14674  return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
14675  && !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
14676 }
14677 
14678 
14679 THREADED_TEST(TurnOnAccessCheckAndRecompile) {
14680  v8::Isolate* isolate = CcTest::isolate();
14681  v8::HandleScope handle_scope(isolate);
14682 
14683  // Create an environment with access check to the global object disabled by
14684  // default. When the registered access checker will block access to properties
14685  // a and h.
14686  v8::Handle<v8::ObjectTemplate> global_template =
14687  v8::ObjectTemplate::New(isolate);
14688  global_template->SetAccessCheckCallbacks(NamedGetAccessBlockAandH,
14689  IndexedGetAccessBlocker,
14691  false);
14692  v8::Local<Context> context = Context::New(isolate, NULL, global_template);
14693  Context::Scope context_scope(context);
14694 
14695  // Set up a property and a number of functions.
14696  context->Global()->Set(v8_str("a"), v8_num(1));
14697  static const char* source = "function f1() {return a;}"
14698  "function f2() {return a;}"
14699  "function g1() {return h();}"
14700  "function g2() {return h();}"
14701  "function h() {return 1;}";
14702 
14703  CompileRun(source);
14704  Local<Function> f1;
14705  Local<Function> f2;
14706  Local<Function> g1;
14707  Local<Function> g2;
14708  Local<Function> h;
14709  f1 = Local<Function>::Cast(context->Global()->Get(v8_str("f1")));
14710  f2 = Local<Function>::Cast(context->Global()->Get(v8_str("f2")));
14711  g1 = Local<Function>::Cast(context->Global()->Get(v8_str("g1")));
14712  g2 = Local<Function>::Cast(context->Global()->Get(v8_str("g2")));
14713  h = Local<Function>::Cast(context->Global()->Get(v8_str("h")));
14714 
14715  // Get the global object.
14716  v8::Handle<v8::Object> global = context->Global();
14717 
14718  // Call f1 one time and f2 a number of times. This will ensure that f1 still
14719  // uses the runtime system to retreive property a whereas f2 uses global load
14720  // inline cache.
14721  CHECK(f1->Call(global, 0, NULL)->Equals(v8_num(1)));
14722  for (int i = 0; i < 4; i++) {
14723  CHECK(f2->Call(global, 0, NULL)->Equals(v8_num(1)));
14724  }
14725 
14726  // Same for g1 and g2.
14727  CHECK(g1->Call(global, 0, NULL)->Equals(v8_num(1)));
14728  for (int i = 0; i < 4; i++) {
14729  CHECK(g2->Call(global, 0, NULL)->Equals(v8_num(1)));
14730  }
14731 
14732  // Detach the global and turn on access check now blocking access to property
14733  // a and function h.
14734  Local<Object> hidden_global = Local<Object>::Cast(
14735  context->Global()->GetPrototype());
14736  context->DetachGlobal();
14737  hidden_global->TurnOnAccessCheck();
14738 
14739  // Failing access check to property get results in undefined.
14740  CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14741  CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14742 
14743  // Failing access check to function call results in exception.
14744  CHECK(g1->Call(global, 0, NULL).IsEmpty());
14745  CHECK(g2->Call(global, 0, NULL).IsEmpty());
14746 
14747  // No failing access check when just returning a constant.
14748  CHECK(h->Call(global, 0, NULL)->Equals(v8_num(1)));
14749 
14750  // Now compile the source again. And get the newly compiled functions, except
14751  // for h for which access is blocked.
14752  CompileRun(source);
14753  f1 = Local<Function>::Cast(hidden_global->Get(v8_str("f1")));
14754  f2 = Local<Function>::Cast(hidden_global->Get(v8_str("f2")));
14755  g1 = Local<Function>::Cast(hidden_global->Get(v8_str("g1")));
14756  g2 = Local<Function>::Cast(hidden_global->Get(v8_str("g2")));
14757  CHECK(hidden_global->Get(v8_str("h"))->IsUndefined());
14758 
14759  // Failing access check to property get results in undefined.
14760  CHECK(f1->Call(global, 0, NULL)->IsUndefined());
14761  CHECK(f2->Call(global, 0, NULL)->IsUndefined());
14762 
14763  // Failing access check to function call results in exception.
14764  CHECK(g1->Call(global, 0, NULL).IsEmpty());
14765  CHECK(g2->Call(global, 0, NULL).IsEmpty());
14766 }
14767 
14768 
14769 // This test verifies that pre-compilation (aka preparsing) can be called
14770 // without initializing the whole VM. Thus we cannot run this test in a
14771 // multi-threaded setup.
14772 TEST(PreCompile) {
14773  // TODO(155): This test would break without the initialization of V8. This is
14774  // a workaround for now to make this test not fail.
14776  v8::Isolate* isolate = CcTest::isolate();
14777  HandleScope handle_scope(isolate);
14778  const char* script = "function foo(a) { return a+1; }";
14780  isolate, script, v8::String::kNormalString, i::StrLength(script)));
14781  CHECK_NE(sd->Length(), 0);
14782  CHECK_NE(sd->Data(), NULL);
14783  CHECK(!sd->HasError());
14784  delete sd;
14785 }
14786 
14787 
14788 TEST(PreCompileWithError) {
14790  v8::Isolate* isolate = CcTest::isolate();
14791  HandleScope handle_scope(isolate);
14792  const char* script = "function foo(a) { return 1 * * 2; }";
14794  isolate, script, v8::String::kNormalString, i::StrLength(script)));
14795  CHECK(sd->HasError());
14796  delete sd;
14797 }
14798 
14799 
14800 TEST(Regress31661) {
14802  v8::Isolate* isolate = CcTest::isolate();
14803  HandleScope handle_scope(isolate);
14804  const char* script = " The Definintive Guide";
14806  isolate, script, v8::String::kNormalString, i::StrLength(script)));
14807  CHECK(sd->HasError());
14808  delete sd;
14809 }
14810 
14811 
14812 // Tests that ScriptData can be serialized and deserialized.
14813 TEST(PreCompileSerialization) {
14815  v8::Isolate* isolate = CcTest::isolate();
14816  HandleScope handle_scope(isolate);
14817  const char* script = "function foo(a) { return a+1; }";
14819  isolate, script, v8::String::kNormalString, i::StrLength(script)));
14820 
14821  // Serialize.
14822  int serialized_data_length = sd->Length();
14823  char* serialized_data = i::NewArray<char>(serialized_data_length);
14824  i::OS::MemCopy(serialized_data, sd->Data(), serialized_data_length);
14825 
14826  // Deserialize.
14827  v8::ScriptData* deserialized_sd =
14828  v8::ScriptData::New(serialized_data, serialized_data_length);
14829 
14830  // Verify that the original is the same as the deserialized.
14831  CHECK_EQ(sd->Length(), deserialized_sd->Length());
14832  CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length()));
14833  CHECK_EQ(sd->HasError(), deserialized_sd->HasError());
14834 
14835  delete sd;
14836  delete deserialized_sd;
14837  i::DeleteArray(serialized_data);
14838 }
14839 
14840 
14841 // Attempts to deserialize bad data.
14842 TEST(PreCompileDeserializationError) {
14844  const char* data = "DONT CARE";
14845  int invalid_size = 3;
14846  v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size);
14847 
14848  CHECK_EQ(0, sd->Length());
14849 
14850  delete sd;
14851 }
14852 
14853 
14854 // Attempts to deserialize bad data.
14855 TEST(PreCompileInvalidPreparseDataError) {
14857  v8::Isolate* isolate = CcTest::isolate();
14858  LocalContext context;
14859  v8::HandleScope scope(context->GetIsolate());
14860 
14861  const char* script = "function foo(){ return 5;}\n"
14862  "function bar(){ return 6 + 7;} foo();";
14864  isolate, script, v8::String::kNormalString, i::StrLength(script)));
14865  CHECK(!sd->HasError());
14866  // ScriptDataImpl private implementation details
14867  const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
14868  const int kFunctionEntrySize = i::FunctionEntry::kSize;
14869  const int kFunctionEntryStartOffset = 0;
14870  const int kFunctionEntryEndOffset = 1;
14871  unsigned* sd_data =
14872  reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
14873 
14874  // Overwrite function bar's end position with 0.
14875  sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryEndOffset] = 0;
14876  v8::TryCatch try_catch;
14877 
14878  v8::ScriptCompiler::Source script_source(
14879  String::NewFromUtf8(isolate, script),
14881  reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length()));
14882  Local<v8::UnboundScript> compiled_script =
14883  v8::ScriptCompiler::CompileUnbound(isolate, &script_source);
14884 
14885  CHECK(try_catch.HasCaught());
14886  String::Utf8Value exception_value(try_catch.Message()->Get());
14887  CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar",
14888  *exception_value);
14889 
14890  try_catch.Reset();
14891  delete sd;
14892 
14893  // Overwrite function bar's start position with 200. The function entry
14894  // will not be found when searching for it by position and we should fall
14895  // back on eager compilation.
14897  isolate, script, v8::String::kNormalString, i::StrLength(script)));
14898  sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
14899  sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
14900  200;
14901  v8::ScriptCompiler::Source script_source2(
14902  String::NewFromUtf8(isolate, script),
14904  reinterpret_cast<const uint8_t*>(sd->Data()), sd->Length()));
14905  compiled_script =
14906  v8::ScriptCompiler::CompileUnbound(isolate, &script_source2);
14907  CHECK(!try_catch.HasCaught());
14908 
14909  delete sd;
14910 }
14911 
14912 
14913 // This tests that we do not allow dictionary load/call inline caches
14914 // to use functions that have not yet been compiled. The potential
14915 // problem of loading a function that has not yet been compiled can
14916 // arise because we share code between contexts via the compilation
14917 // cache.
14918 THREADED_TEST(DictionaryICLoadedFunction) {
14920  // Test LoadIC.
14921  for (int i = 0; i < 2; i++) {
14922  LocalContext context;
14923  context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
14924  context->Global()->Delete(v8_str("tmp"));
14925  CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
14926  }
14927  // Test CallIC.
14928  for (int i = 0; i < 2; i++) {
14929  LocalContext context;
14930  context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
14931  context->Global()->Delete(v8_str("tmp"));
14932  CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
14933  }
14934 }
14935 
14936 
14937 // Test that cross-context new calls use the context of the callee to
14938 // create the new JavaScript object.
14939 THREADED_TEST(CrossContextNew) {
14940  v8::Isolate* isolate = CcTest::isolate();
14941  v8::HandleScope scope(isolate);
14942  v8::Local<Context> context0 = Context::New(isolate);
14943  v8::Local<Context> context1 = Context::New(isolate);
14944 
14945  // Allow cross-domain access.
14946  Local<String> token = v8_str("<security token>");
14947  context0->SetSecurityToken(token);
14948  context1->SetSecurityToken(token);
14949 
14950  // Set an 'x' property on the Object prototype and define a
14951  // constructor function in context0.
14952  context0->Enter();
14953  CompileRun("Object.prototype.x = 42; function C() {};");
14954  context0->Exit();
14955 
14956  // Call the constructor function from context0 and check that the
14957  // result has the 'x' property.
14958  context1->Enter();
14959  context1->Global()->Set(v8_str("other"), context0->Global());
14960  Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
14961  CHECK(value->IsInt32());
14962  CHECK_EQ(42, value->Int32Value());
14963  context1->Exit();
14964 }
14965 
14966 
14967 // Verify that we can clone an object
14968 TEST(ObjectClone) {
14969  LocalContext env;
14970  v8::Isolate* isolate = env->GetIsolate();
14971  v8::HandleScope scope(isolate);
14972 
14973  const char* sample =
14974  "var rv = {};" \
14975  "rv.alpha = 'hello';" \
14976  "rv.beta = 123;" \
14977  "rv;";
14978 
14979  // Create an object, verify basics.
14980  Local<Value> val = CompileRun(sample);
14981  CHECK(val->IsObject());
14982  Local<v8::Object> obj = val.As<v8::Object>();
14983  obj->Set(v8_str("gamma"), v8_str("cloneme"));
14984 
14985  CHECK_EQ(v8_str("hello"), obj->Get(v8_str("alpha")));
14986  CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
14987  CHECK_EQ(v8_str("cloneme"), obj->Get(v8_str("gamma")));
14988 
14989  // Clone it.
14990  Local<v8::Object> clone = obj->Clone();
14991  CHECK_EQ(v8_str("hello"), clone->Get(v8_str("alpha")));
14992  CHECK_EQ(v8::Integer::New(isolate, 123), clone->Get(v8_str("beta")));
14993  CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma")));
14994 
14995  // Set a property on the clone, verify each object.
14996  clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
14997  CHECK_EQ(v8::Integer::New(isolate, 123), obj->Get(v8_str("beta")));
14998  CHECK_EQ(v8::Integer::New(isolate, 456), clone->Get(v8_str("beta")));
14999 }
15000 
15001 
15003  public:
15005  : data_(vector) {}
15007  virtual size_t length() const { return data_.length(); }
15008  virtual const char* data() const { return data_.start(); }
15009  private:
15010  i::Vector<const char> data_;
15011 };
15012 
15013 
15015  public:
15017  : data_(vector) {}
15018  virtual ~UC16VectorResource() {}
15019  virtual size_t length() const { return data_.length(); }
15020  virtual const i::uc16* data() const { return data_.start(); }
15021  private:
15023 };
15024 
15025 
15026 static void MorphAString(i::String* string,
15027  AsciiVectorResource* ascii_resource,
15028  UC16VectorResource* uc16_resource) {
15029  CHECK(i::StringShape(string).IsExternal());
15030  if (string->IsOneByteRepresentation()) {
15031  // Check old map is not internalized or long.
15032  CHECK(string->map() == CcTest::heap()->external_ascii_string_map());
15033  // Morph external string to be TwoByte string.
15034  string->set_map(CcTest::heap()->external_string_map());
15035  i::ExternalTwoByteString* morphed =
15037  morphed->set_resource(uc16_resource);
15038  } else {
15039  // Check old map is not internalized or long.
15040  CHECK(string->map() == CcTest::heap()->external_string_map());
15041  // Morph external string to be ASCII string.
15042  string->set_map(CcTest::heap()->external_ascii_string_map());
15043  i::ExternalAsciiString* morphed =
15045  morphed->set_resource(ascii_resource);
15046  }
15047 }
15048 
15049 
15050 // Test that we can still flatten a string if the components it is built up
15051 // from have been turned into 16 bit strings in the mean time.
15052 THREADED_TEST(MorphCompositeStringTest) {
15053  char utf_buffer[129];
15054  const char* c_string = "Now is the time for all good men"
15055  " to come to the aid of the party";
15056  uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
15057  {
15058  LocalContext env;
15059  i::Factory* factory = CcTest::i_isolate()->factory();
15060  v8::HandleScope scope(env->GetIsolate());
15061  AsciiVectorResource ascii_resource(
15062  i::Vector<const char>(c_string, i::StrLength(c_string)));
15063  UC16VectorResource uc16_resource(
15064  i::Vector<const uint16_t>(two_byte_string,
15065  i::StrLength(c_string)));
15066 
15067  Local<String> lhs(v8::Utils::ToLocal(
15068  factory->NewExternalStringFromAscii(&ascii_resource)));
15069  Local<String> rhs(v8::Utils::ToLocal(
15070  factory->NewExternalStringFromAscii(&ascii_resource)));
15071 
15072  env->Global()->Set(v8_str("lhs"), lhs);
15073  env->Global()->Set(v8_str("rhs"), rhs);
15074 
15075  CompileRun(
15076  "var cons = lhs + rhs;"
15077  "var slice = lhs.substring(1, lhs.length - 1);"
15078  "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
15079 
15080  CHECK(lhs->IsOneByte());
15081  CHECK(rhs->IsOneByte());
15082 
15083  MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource);
15084  MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource);
15085 
15086  // This should UTF-8 without flattening, since everything is ASCII.
15087  Handle<String> cons = v8_compile("cons")->Run().As<String>();
15088  CHECK_EQ(128, cons->Utf8Length());
15089  int nchars = -1;
15090  CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
15091  CHECK_EQ(128, nchars);
15092  CHECK_EQ(0, strcmp(
15093  utf_buffer,
15094  "Now is the time for all good men to come to the aid of the party"
15095  "Now is the time for all good men to come to the aid of the party"));
15096 
15097  // Now do some stuff to make sure the strings are flattened, etc.
15098  CompileRun(
15099  "/[^a-z]/.test(cons);"
15100  "/[^a-z]/.test(slice);"
15101  "/[^a-z]/.test(slice_on_cons);");
15102  const char* expected_cons =
15103  "Now is the time for all good men to come to the aid of the party"
15104  "Now is the time for all good men to come to the aid of the party";
15105  const char* expected_slice =
15106  "ow is the time for all good men to come to the aid of the part";
15107  const char* expected_slice_on_cons =
15108  "ow is the time for all good men to come to the aid of the party"
15109  "Now is the time for all good men to come to the aid of the part";
15110  CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_cons),
15111  env->Global()->Get(v8_str("cons")));
15112  CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice),
15113  env->Global()->Get(v8_str("slice")));
15114  CHECK_EQ(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons),
15115  env->Global()->Get(v8_str("slice_on_cons")));
15116  }
15117  i::DeleteArray(two_byte_string);
15118 }
15119 
15120 
15121 TEST(CompileExternalTwoByteSource) {
15122  LocalContext context;
15123  v8::HandleScope scope(context->GetIsolate());
15124 
15125  // This is a very short list of sources, which currently is to check for a
15126  // regression caused by r2703.
15127  const char* ascii_sources[] = {
15128  "0.5",
15129  "-0.5", // This mainly testes PushBack in the Scanner.
15130  "--0.5", // This mainly testes PushBack in the Scanner.
15131  NULL
15132  };
15133 
15134  // Compile the sources as external two byte strings.
15135  for (int i = 0; ascii_sources[i] != NULL; i++) {
15136  uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
15137  TestResource* uc16_resource = new TestResource(two_byte_string);
15138  v8::Local<v8::String> source =
15139  v8::String::NewExternal(context->GetIsolate(), uc16_resource);
15140  v8::Script::Compile(source);
15141  }
15142 }
15143 
15144 
15145 #ifndef V8_INTERPRETED_REGEXP
15146 
15152 
15153 
15155  public:
15157  : Thread("TimeoutThread"), isolate_(isolate) {}
15158 
15159  virtual void Run() {
15163  i::OS::Sleep(50); // Wait a bit before requesting GC.
15164  reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
15165  }
15166  i::OS::Sleep(50); // Wait a bit before terminating.
15167  v8::V8::TerminateExecution(isolate_);
15168  }
15169 
15170  private:
15171  v8::Isolate* isolate_;
15172 };
15173 
15174 
15176  if (regexp_interruption_data.loop_count != 2) return;
15180  string->MakeExternal(regexp_interruption_data.string_resource);
15181 }
15182 
15183 
15184 // Test that RegExp execution can be interrupted. Specifically, we test
15185 // * interrupting with GC
15186 // * turn the subject string from one-byte internal to two-byte external string
15187 // * force termination
15188 TEST(RegExpInterruption) {
15190  LocalContext env;
15191 
15192  RegExpInterruptionThread timeout_thread(CcTest::isolate());
15193 
15195  static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
15196  i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
15197  v8::Local<v8::String> string = v8_str(ascii_content);
15198 
15199  CcTest::global()->Set(v8_str("a"), string);
15202  i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
15203 
15204  v8::TryCatch try_catch;
15205  timeout_thread.Start();
15206 
15207  CompileRun("/((a*)*)*b/.exec(a)");
15208  CHECK(try_catch.HasTerminated());
15209 
15210  timeout_thread.Join();
15211 
15213  i::DeleteArray(uc16_content);
15214 }
15215 
15216 #endif // V8_INTERPRETED_REGEXP
15217 
15218 
15219 // Test that we cannot set a property on the global object if there
15220 // is a read-only property in the prototype chain.
15221 TEST(ReadOnlyPropertyInGlobalProto) {
15222  v8::Isolate* isolate = CcTest::isolate();
15223  v8::HandleScope scope(isolate);
15225  LocalContext context(0, templ);
15226  v8::Handle<v8::Object> global = context->Global();
15227  v8::Handle<v8::Object> global_proto =
15228  v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
15229  global_proto->Set(v8_str("x"), v8::Integer::New(isolate, 0), v8::ReadOnly);
15230  global_proto->Set(v8_str("y"), v8::Integer::New(isolate, 0), v8::ReadOnly);
15231  // Check without 'eval' or 'with'.
15232  v8::Handle<v8::Value> res =
15233  CompileRun("function f() { x = 42; return x; }; f()");
15234  CHECK_EQ(v8::Integer::New(isolate, 0), res);
15235  // Check with 'eval'.
15236  res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
15237  CHECK_EQ(v8::Integer::New(isolate, 0), res);
15238  // Check with 'with'.
15239  res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
15240  CHECK_EQ(v8::Integer::New(isolate, 0), res);
15241 }
15242 
15243 static int force_set_set_count = 0;
15244 static int force_set_get_count = 0;
15245 bool pass_on_get = false;
15246 
15247 static void ForceSetGetter(v8::Local<v8::String> name,
15249  force_set_get_count++;
15250  if (pass_on_get) {
15251  return;
15252  }
15253  info.GetReturnValue().Set(3);
15254 }
15255 
15256 static void ForceSetSetter(v8::Local<v8::String> name,
15257  v8::Local<v8::Value> value,
15258  const v8::PropertyCallbackInfo<void>& info) {
15259  force_set_set_count++;
15260 }
15261 
15262 static void ForceSetInterceptSetter(
15263  v8::Local<v8::String> name,
15264  v8::Local<v8::Value> value,
15266  force_set_set_count++;
15267  info.GetReturnValue().SetUndefined();
15268 }
15269 
15270 
15271 TEST(ForceSet) {
15272  force_set_get_count = 0;
15273  force_set_set_count = 0;
15274  pass_on_get = false;
15275 
15276  v8::Isolate* isolate = CcTest::isolate();
15277  v8::HandleScope scope(isolate);
15279  v8::Handle<v8::String> access_property =
15280  v8::String::NewFromUtf8(isolate, "a");
15281  templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
15282  LocalContext context(NULL, templ);
15283  v8::Handle<v8::Object> global = context->Global();
15284 
15285  // Ordinary properties
15286  v8::Handle<v8::String> simple_property =
15287  v8::String::NewFromUtf8(isolate, "p");
15288  global->Set(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
15289  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15290  // This should fail because the property is read-only
15291  global->Set(simple_property, v8::Int32::New(isolate, 5));
15292  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15293  // This should succeed even though the property is read-only
15294  global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
15295  CHECK_EQ(6, global->Get(simple_property)->Int32Value());
15296 
15297  // Accessors
15298  CHECK_EQ(0, force_set_set_count);
15299  CHECK_EQ(0, force_set_get_count);
15300  CHECK_EQ(3, global->Get(access_property)->Int32Value());
15301  // CHECK_EQ the property shouldn't override it, just call the setter
15302  // which in this case does nothing.
15303  global->Set(access_property, v8::Int32::New(isolate, 7));
15304  CHECK_EQ(3, global->Get(access_property)->Int32Value());
15305  CHECK_EQ(1, force_set_set_count);
15306  CHECK_EQ(2, force_set_get_count);
15307  // Forcing the property to be set should override the accessor without
15308  // calling it
15309  global->ForceSet(access_property, v8::Int32::New(isolate, 8));
15310  CHECK_EQ(8, global->Get(access_property)->Int32Value());
15311  CHECK_EQ(1, force_set_set_count);
15312  CHECK_EQ(2, force_set_get_count);
15313 }
15314 
15315 
15316 TEST(ForceSetWithInterceptor) {
15317  force_set_get_count = 0;
15318  force_set_set_count = 0;
15319  pass_on_get = false;
15320 
15321  v8::Isolate* isolate = CcTest::isolate();
15322  v8::HandleScope scope(isolate);
15324  templ->SetNamedPropertyHandler(ForceSetGetter, ForceSetInterceptSetter);
15325  LocalContext context(NULL, templ);
15326  v8::Handle<v8::Object> global = context->Global();
15327 
15328  v8::Handle<v8::String> some_property =
15329  v8::String::NewFromUtf8(isolate, "a");
15330  CHECK_EQ(0, force_set_set_count);
15331  CHECK_EQ(0, force_set_get_count);
15332  CHECK_EQ(3, global->Get(some_property)->Int32Value());
15333  // Setting the property shouldn't override it, just call the setter
15334  // which in this case does nothing.
15335  global->Set(some_property, v8::Int32::New(isolate, 7));
15336  CHECK_EQ(3, global->Get(some_property)->Int32Value());
15337  CHECK_EQ(1, force_set_set_count);
15338  CHECK_EQ(2, force_set_get_count);
15339  // Getting the property when the interceptor returns an empty handle
15340  // should yield undefined, since the property isn't present on the
15341  // object itself yet.
15342  pass_on_get = true;
15343  CHECK(global->Get(some_property)->IsUndefined());
15344  CHECK_EQ(1, force_set_set_count);
15345  CHECK_EQ(3, force_set_get_count);
15346  // Forcing the property to be set should cause the value to be
15347  // set locally without calling the interceptor.
15348  global->ForceSet(some_property, v8::Int32::New(isolate, 8));
15349  CHECK_EQ(8, global->Get(some_property)->Int32Value());
15350  CHECK_EQ(1, force_set_set_count);
15351  CHECK_EQ(4, force_set_get_count);
15352  // Reenabling the interceptor should cause it to take precedence over
15353  // the property
15354  pass_on_get = false;
15355  CHECK_EQ(3, global->Get(some_property)->Int32Value());
15356  CHECK_EQ(1, force_set_set_count);
15357  CHECK_EQ(5, force_set_get_count);
15358  // The interceptor should also work for other properties
15359  CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
15360  ->Int32Value());
15361  CHECK_EQ(1, force_set_set_count);
15362  CHECK_EQ(6, force_set_get_count);
15363 }
15364 
15365 
15366 THREADED_TEST(ForceDelete) {
15367  v8::Isolate* isolate = CcTest::isolate();
15368  v8::HandleScope scope(isolate);
15370  LocalContext context(NULL, templ);
15371  v8::Handle<v8::Object> global = context->Global();
15372 
15373  // Ordinary properties
15374  v8::Handle<v8::String> simple_property =
15375  v8::String::NewFromUtf8(isolate, "p");
15376  global->Set(simple_property, v8::Int32::New(isolate, 4), v8::DontDelete);
15377  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15378  // This should fail because the property is dont-delete.
15379  CHECK(!global->Delete(simple_property));
15380  CHECK_EQ(4, global->Get(simple_property)->Int32Value());
15381  // This should succeed even though the property is dont-delete.
15382  CHECK(global->ForceDelete(simple_property));
15383  CHECK(global->Get(simple_property)->IsUndefined());
15384 }
15385 
15386 
15387 static int force_delete_interceptor_count = 0;
15388 static bool pass_on_delete = false;
15389 
15390 
15391 static void ForceDeleteDeleter(
15392  v8::Local<v8::String> name,
15394  force_delete_interceptor_count++;
15395  if (pass_on_delete) return;
15396  info.GetReturnValue().Set(true);
15397 }
15398 
15399 
15400 THREADED_TEST(ForceDeleteWithInterceptor) {
15401  force_delete_interceptor_count = 0;
15402  pass_on_delete = false;
15403 
15404  v8::Isolate* isolate = CcTest::isolate();
15405  v8::HandleScope scope(isolate);
15407  templ->SetNamedPropertyHandler(0, 0, 0, ForceDeleteDeleter);
15408  LocalContext context(NULL, templ);
15409  v8::Handle<v8::Object> global = context->Global();
15410 
15411  v8::Handle<v8::String> some_property =
15412  v8::String::NewFromUtf8(isolate, "a");
15413  global->Set(some_property, v8::Integer::New(isolate, 42), v8::DontDelete);
15414 
15415  // Deleting a property should get intercepted and nothing should
15416  // happen.
15417  CHECK_EQ(0, force_delete_interceptor_count);
15418  CHECK(global->Delete(some_property));
15419  CHECK_EQ(1, force_delete_interceptor_count);
15420  CHECK_EQ(42, global->Get(some_property)->Int32Value());
15421  // Deleting the property when the interceptor returns an empty
15422  // handle should not delete the property since it is DontDelete.
15423  pass_on_delete = true;
15424  CHECK(!global->Delete(some_property));
15425  CHECK_EQ(2, force_delete_interceptor_count);
15426  CHECK_EQ(42, global->Get(some_property)->Int32Value());
15427  // Forcing the property to be deleted should delete the value
15428  // without calling the interceptor.
15429  CHECK(global->ForceDelete(some_property));
15430  CHECK(global->Get(some_property)->IsUndefined());
15431  CHECK_EQ(2, force_delete_interceptor_count);
15432 }
15433 
15434 
15435 // Make sure that forcing a delete invalidates any IC stubs, so we
15436 // don't read the hole value.
15437 THREADED_TEST(ForceDeleteIC) {
15438  LocalContext context;
15439  v8::HandleScope scope(context->GetIsolate());
15440  // Create a DontDelete variable on the global object.
15441  CompileRun("this.__proto__ = { foo: 'horse' };"
15442  "var foo = 'fish';"
15443  "function f() { return foo.length; }");
15444  // Initialize the IC for foo in f.
15445  CompileRun("for (var i = 0; i < 4; i++) f();");
15446  // Make sure the value of foo is correct before the deletion.
15447  CHECK_EQ(4, CompileRun("f()")->Int32Value());
15448  // Force the deletion of foo.
15449  CHECK(context->Global()->ForceDelete(v8_str("foo")));
15450  // Make sure the value for foo is read from the prototype, and that
15451  // we don't get in trouble with reading the deleted cell value
15452  // sentinel.
15453  CHECK_EQ(5, CompileRun("f()")->Int32Value());
15454 }
15455 
15456 
15457 TEST(InlinedFunctionAcrossContexts) {
15458  i::FLAG_allow_natives_syntax = true;
15459  v8::Isolate* isolate = CcTest::isolate();
15460  v8::HandleScope outer_scope(isolate);
15461  v8::Local<v8::Context> ctx1 = v8::Context::New(isolate);
15462  v8::Local<v8::Context> ctx2 = v8::Context::New(isolate);
15463  ctx1->Enter();
15464 
15465  {
15466  v8::HandleScope inner_scope(CcTest::isolate());
15467  CompileRun("var G = 42; function foo() { return G; }");
15468  v8::Local<v8::Value> foo = ctx1->Global()->Get(v8_str("foo"));
15469  ctx2->Enter();
15470  ctx2->Global()->Set(v8_str("o"), foo);
15471  v8::Local<v8::Value> res = CompileRun(
15472  "function f() { return o(); }"
15473  "for (var i = 0; i < 10; ++i) f();"
15474  "%OptimizeFunctionOnNextCall(f);"
15475  "f();");
15476  CHECK_EQ(42, res->Int32Value());
15477  ctx2->Exit();
15478  v8::Handle<v8::String> G_property =
15480  CHECK(ctx1->Global()->ForceDelete(G_property));
15481  ctx2->Enter();
15482  ExpectString(
15483  "(function() {"
15484  " try {"
15485  " return f();"
15486  " } catch(e) {"
15487  " return e.toString();"
15488  " }"
15489  " })()",
15490  "ReferenceError: G is not defined");
15491  ctx2->Exit();
15492  ctx1->Exit();
15493  }
15494 }
15495 
15496 
15497 static v8::Local<Context> calling_context0;
15498 static v8::Local<Context> calling_context1;
15499 static v8::Local<Context> calling_context2;
15500 
15501 
15502 // Check that the call to the callback is initiated in
15503 // calling_context2, the directly calling context is calling_context1
15504 // and the callback itself is in calling_context0.
15505 static void GetCallingContextCallback(
15508  CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
15509  CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
15510  CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
15511  args.GetReturnValue().Set(42);
15512 }
15513 
15514 
15515 THREADED_TEST(GetCurrentContextWhenNotInContext) {
15516  i::Isolate* isolate = CcTest::i_isolate();
15517  CHECK(isolate != NULL);
15518  CHECK(isolate->context() == NULL);
15519  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
15520  v8::HandleScope scope(v8_isolate);
15521  // The following should not crash, but return an empty handle.
15522  v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
15523  CHECK(current.IsEmpty());
15524 }
15525 
15526 
15527 THREADED_TEST(GetCallingContext) {
15528  v8::Isolate* isolate = CcTest::isolate();
15529  v8::HandleScope scope(isolate);
15530 
15531  Local<Context> calling_context0(Context::New(isolate));
15532  Local<Context> calling_context1(Context::New(isolate));
15533  Local<Context> calling_context2(Context::New(isolate));
15534  ::calling_context0 = calling_context0;
15535  ::calling_context1 = calling_context1;
15536  ::calling_context2 = calling_context2;
15537 
15538  // Allow cross-domain access.
15539  Local<String> token = v8_str("<security token>");
15540  calling_context0->SetSecurityToken(token);
15541  calling_context1->SetSecurityToken(token);
15542  calling_context2->SetSecurityToken(token);
15543 
15544  // Create an object with a C++ callback in context0.
15545  calling_context0->Enter();
15546  Local<v8::FunctionTemplate> callback_templ =
15547  v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
15548  calling_context0->Global()->Set(v8_str("callback"),
15549  callback_templ->GetFunction());
15550  calling_context0->Exit();
15551 
15552  // Expose context0 in context1 and set up a function that calls the
15553  // callback function.
15554  calling_context1->Enter();
15555  calling_context1->Global()->Set(v8_str("context0"),
15556  calling_context0->Global());
15557  CompileRun("function f() { context0.callback() }");
15558  calling_context1->Exit();
15559 
15560  // Expose context1 in context2 and call the callback function in
15561  // context0 indirectly through f in context1.
15562  calling_context2->Enter();
15563  calling_context2->Global()->Set(v8_str("context1"),
15564  calling_context1->Global());
15565  CompileRun("context1.f()");
15566  calling_context2->Exit();
15567  ::calling_context0.Clear();
15568  ::calling_context1.Clear();
15569  ::calling_context2.Clear();
15570 }
15571 
15572 
15573 // Check that a variable declaration with no explicit initialization
15574 // value does shadow an existing property in the prototype chain.
15575 THREADED_TEST(InitGlobalVarInProtoChain) {
15576  LocalContext context;
15577  v8::HandleScope scope(context->GetIsolate());
15578  // Introduce a variable in the prototype chain.
15579  CompileRun("__proto__.x = 42");
15580  v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
15581  CHECK(!result->IsUndefined());
15582  CHECK_EQ(43, result->Int32Value());
15583 }
15584 
15585 
15586 // Regression test for issue 398.
15587 // If a function is added to an object, creating a constant function
15588 // field, and the result is cloned, replacing the constant function on the
15589 // original should not affect the clone.
15590 // See http://code.google.com/p/v8/issues/detail?id=398
15591 THREADED_TEST(ReplaceConstantFunction) {
15592  LocalContext context;
15593  v8::Isolate* isolate = context->GetIsolate();
15594  v8::HandleScope scope(isolate);
15595  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
15597  v8::FunctionTemplate::New(isolate);
15598  v8::Handle<v8::String> foo_string =
15599  v8::String::NewFromUtf8(isolate, "foo");
15600  obj->Set(foo_string, func_templ->GetFunction());
15601  v8::Handle<v8::Object> obj_clone = obj->Clone();
15602  obj_clone->Set(foo_string,
15603  v8::String::NewFromUtf8(isolate, "Hello"));
15604  CHECK(!obj->Get(foo_string)->IsUndefined());
15605 }
15606 
15607 
15608 static void CheckElementValue(i::Isolate* isolate,
15609  int expected,
15611  int offset) {
15612  i::Object* element = *i::Object::GetElement(isolate, obj, offset);
15613  CHECK_EQ(expected, i::Smi::cast(element)->value());
15614 }
15615 
15616 
15617 THREADED_TEST(PixelArray) {
15618  LocalContext context;
15619  i::Isolate* isolate = CcTest::i_isolate();
15620  i::Factory* factory = isolate->factory();
15621  v8::HandleScope scope(context->GetIsolate());
15622  const int kElementCount = 260;
15623  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
15626  factory->NewExternalArray(kElementCount,
15628  pixel_data));
15629  // Force GC to trigger verification.
15631  for (int i = 0; i < kElementCount; i++) {
15632  pixels->set(i, i % 256);
15633  }
15634  // Force GC to trigger verification.
15636  for (int i = 0; i < kElementCount; i++) {
15637  CHECK_EQ(i % 256, pixels->get_scalar(i));
15638  CHECK_EQ(i % 256, pixel_data[i]);
15639  }
15640 
15643  // Set the elements to be the pixels.
15644  // jsobj->set_elements(*pixels);
15645  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
15646  CheckElementValue(isolate, 1, jsobj, 1);
15647  obj->Set(v8_str("field"), v8::Int32::New(CcTest::isolate(), 1503));
15648  context->Global()->Set(v8_str("pixels"), obj);
15649  v8::Handle<v8::Value> result = CompileRun("pixels.field");
15650  CHECK_EQ(1503, result->Int32Value());
15651  result = CompileRun("pixels[1]");
15652  CHECK_EQ(1, result->Int32Value());
15653 
15654  result = CompileRun("var sum = 0;"
15655  "for (var i = 0; i < 8; i++) {"
15656  " sum += pixels[i] = pixels[i] = -i;"
15657  "}"
15658  "sum;");
15659  CHECK_EQ(-28, result->Int32Value());
15660 
15661  result = CompileRun("var sum = 0;"
15662  "for (var i = 0; i < 8; i++) {"
15663  " sum += pixels[i] = pixels[i] = 0;"
15664  "}"
15665  "sum;");
15666  CHECK_EQ(0, result->Int32Value());
15667 
15668  result = CompileRun("var sum = 0;"
15669  "for (var i = 0; i < 8; i++) {"
15670  " sum += pixels[i] = pixels[i] = 255;"
15671  "}"
15672  "sum;");
15673  CHECK_EQ(8 * 255, result->Int32Value());
15674 
15675  result = CompileRun("var sum = 0;"
15676  "for (var i = 0; i < 8; i++) {"
15677  " sum += pixels[i] = pixels[i] = 256 + i;"
15678  "}"
15679  "sum;");
15680  CHECK_EQ(2076, result->Int32Value());
15681 
15682  result = CompileRun("var sum = 0;"
15683  "for (var i = 0; i < 8; i++) {"
15684  " sum += pixels[i] = pixels[i] = i;"
15685  "}"
15686  "sum;");
15687  CHECK_EQ(28, result->Int32Value());
15688 
15689  result = CompileRun("var sum = 0;"
15690  "for (var i = 0; i < 8; i++) {"
15691  " sum += pixels[i];"
15692  "}"
15693  "sum;");
15694  CHECK_EQ(28, result->Int32Value());
15695 
15697  reinterpret_cast<i::Isolate*>(context->GetIsolate()));
15698  i::Handle<i::Object> no_failure;
15699  no_failure = i::JSObject::SetElement(jsobj, 1, value, NONE, i::SLOPPY);
15700  ASSERT(!no_failure.is_null());
15701  i::USE(no_failure);
15702  CheckElementValue(isolate, 2, jsobj, 1);
15703  *value.location() = i::Smi::FromInt(256);
15704  no_failure = i::JSObject::SetElement(jsobj, 1, value, NONE, i::SLOPPY);
15705  ASSERT(!no_failure.is_null());
15706  i::USE(no_failure);
15707  CheckElementValue(isolate, 255, jsobj, 1);
15708  *value.location() = i::Smi::FromInt(-1);
15709  no_failure = i::JSObject::SetElement(jsobj, 1, value, NONE, i::SLOPPY);
15710  ASSERT(!no_failure.is_null());
15711  i::USE(no_failure);
15712  CheckElementValue(isolate, 0, jsobj, 1);
15713 
15714  result = CompileRun("for (var i = 0; i < 8; i++) {"
15715  " pixels[i] = (i * 65) - 109;"
15716  "}"
15717  "pixels[1] + pixels[6];");
15718  CHECK_EQ(255, result->Int32Value());
15719  CheckElementValue(isolate, 0, jsobj, 0);
15720  CheckElementValue(isolate, 0, jsobj, 1);
15721  CheckElementValue(isolate, 21, jsobj, 2);
15722  CheckElementValue(isolate, 86, jsobj, 3);
15723  CheckElementValue(isolate, 151, jsobj, 4);
15724  CheckElementValue(isolate, 216, jsobj, 5);
15725  CheckElementValue(isolate, 255, jsobj, 6);
15726  CheckElementValue(isolate, 255, jsobj, 7);
15727  result = CompileRun("var sum = 0;"
15728  "for (var i = 0; i < 8; i++) {"
15729  " sum += pixels[i];"
15730  "}"
15731  "sum;");
15732  CHECK_EQ(984, result->Int32Value());
15733 
15734  result = CompileRun("for (var i = 0; i < 8; i++) {"
15735  " pixels[i] = (i * 1.1);"
15736  "}"
15737  "pixels[1] + pixels[6];");
15738  CHECK_EQ(8, result->Int32Value());
15739  CheckElementValue(isolate, 0, jsobj, 0);
15740  CheckElementValue(isolate, 1, jsobj, 1);
15741  CheckElementValue(isolate, 2, jsobj, 2);
15742  CheckElementValue(isolate, 3, jsobj, 3);
15743  CheckElementValue(isolate, 4, jsobj, 4);
15744  CheckElementValue(isolate, 6, jsobj, 5);
15745  CheckElementValue(isolate, 7, jsobj, 6);
15746  CheckElementValue(isolate, 8, jsobj, 7);
15747 
15748  result = CompileRun("for (var i = 0; i < 8; i++) {"
15749  " pixels[7] = undefined;"
15750  "}"
15751  "pixels[7];");
15752  CHECK_EQ(0, result->Int32Value());
15753  CheckElementValue(isolate, 0, jsobj, 7);
15754 
15755  result = CompileRun("for (var i = 0; i < 8; i++) {"
15756  " pixels[6] = '2.3';"
15757  "}"
15758  "pixels[6];");
15759  CHECK_EQ(2, result->Int32Value());
15760  CheckElementValue(isolate, 2, jsobj, 6);
15761 
15762  result = CompileRun("for (var i = 0; i < 8; i++) {"
15763  " pixels[5] = NaN;"
15764  "}"
15765  "pixels[5];");
15766  CHECK_EQ(0, result->Int32Value());
15767  CheckElementValue(isolate, 0, jsobj, 5);
15768 
15769  result = CompileRun("for (var i = 0; i < 8; i++) {"
15770  " pixels[8] = Infinity;"
15771  "}"
15772  "pixels[8];");
15773  CHECK_EQ(255, result->Int32Value());
15774  CheckElementValue(isolate, 255, jsobj, 8);
15775 
15776  result = CompileRun("for (var i = 0; i < 8; i++) {"
15777  " pixels[9] = -Infinity;"
15778  "}"
15779  "pixels[9];");
15780  CHECK_EQ(0, result->Int32Value());
15781  CheckElementValue(isolate, 0, jsobj, 9);
15782 
15783  result = CompileRun("pixels[3] = 33;"
15784  "delete pixels[3];"
15785  "pixels[3];");
15786  CHECK_EQ(33, result->Int32Value());
15787 
15788  result = CompileRun("pixels[0] = 10; pixels[1] = 11;"
15789  "pixels[2] = 12; pixels[3] = 13;"
15790  "pixels.__defineGetter__('2',"
15791  "function() { return 120; });"
15792  "pixels[2];");
15793  CHECK_EQ(12, result->Int32Value());
15794 
15795  result = CompileRun("var js_array = new Array(40);"
15796  "js_array[0] = 77;"
15797  "js_array;");
15798  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15799 
15800  result = CompileRun("pixels[1] = 23;"
15801  "pixels.__proto__ = [];"
15802  "js_array.__proto__ = pixels;"
15803  "js_array.concat(pixels);");
15804  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
15805  CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
15806 
15807  result = CompileRun("pixels[1] = 23;");
15808  CHECK_EQ(23, result->Int32Value());
15809 
15810  // Test for index greater than 255. Regression test for:
15811  // http://code.google.com/p/chromium/issues/detail?id=26337.
15812  result = CompileRun("pixels[256] = 255;");
15813  CHECK_EQ(255, result->Int32Value());
15814  result = CompileRun("var i = 0;"
15815  "for (var j = 0; j < 8; j++) { i = pixels[256]; }"
15816  "i");
15817  CHECK_EQ(255, result->Int32Value());
15818 
15819  // Make sure that pixel array ICs recognize when a non-pixel array
15820  // is passed to it.
15821  result = CompileRun("function pa_load(p) {"
15822  " var sum = 0;"
15823  " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15824  " return sum;"
15825  "}"
15826  "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15827  "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15828  "just_ints = new Object();"
15829  "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15830  "for (var i = 0; i < 10; ++i) {"
15831  " result = pa_load(just_ints);"
15832  "}"
15833  "result");
15834  CHECK_EQ(32640, result->Int32Value());
15835 
15836  // Make sure that pixel array ICs recognize out-of-bound accesses.
15837  result = CompileRun("function pa_load(p, start) {"
15838  " var sum = 0;"
15839  " for (var j = start; j < 256; j++) { sum += p[j]; }"
15840  " return sum;"
15841  "}"
15842  "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15843  "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15844  "for (var i = 0; i < 10; ++i) {"
15845  " result = pa_load(pixels,-10);"
15846  "}"
15847  "result");
15848  CHECK_EQ(0, result->Int32Value());
15849 
15850  // Make sure that generic ICs properly handles a pixel array.
15851  result = CompileRun("function pa_load(p) {"
15852  " var sum = 0;"
15853  " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15854  " return sum;"
15855  "}"
15856  "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15857  "just_ints = new Object();"
15858  "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15859  "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15860  "for (var i = 0; i < 10; ++i) {"
15861  " result = pa_load(pixels);"
15862  "}"
15863  "result");
15864  CHECK_EQ(32640, result->Int32Value());
15865 
15866  // Make sure that generic load ICs recognize out-of-bound accesses in
15867  // pixel arrays.
15868  result = CompileRun("function pa_load(p, start) {"
15869  " var sum = 0;"
15870  " for (var j = start; j < 256; j++) { sum += p[j]; }"
15871  " return sum;"
15872  "}"
15873  "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15874  "just_ints = new Object();"
15875  "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15876  "for (var i = 0; i < 10; ++i) { pa_load(just_ints,0); }"
15877  "for (var i = 0; i < 10; ++i) { pa_load(pixels,0); }"
15878  "for (var i = 0; i < 10; ++i) {"
15879  " result = pa_load(pixels,-10);"
15880  "}"
15881  "result");
15882  CHECK_EQ(0, result->Int32Value());
15883 
15884  // Make sure that generic ICs properly handles other types than pixel
15885  // arrays (that the inlined fast pixel array test leaves the right information
15886  // in the right registers).
15887  result = CompileRun("function pa_load(p) {"
15888  " var sum = 0;"
15889  " for (var j = 0; j < 256; j++) { sum += p[j]; }"
15890  " return sum;"
15891  "}"
15892  "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15893  "just_ints = new Object();"
15894  "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15895  "for (var i = 0; i < 10; ++i) { pa_load(just_ints); }"
15896  "for (var i = 0; i < 10; ++i) { pa_load(pixels); }"
15897  "sparse_array = new Object();"
15898  "for (var i = 0; i < 256; ++i) { sparse_array[i] = i; }"
15899  "sparse_array[1000000] = 3;"
15900  "for (var i = 0; i < 10; ++i) {"
15901  " result = pa_load(sparse_array);"
15902  "}"
15903  "result");
15904  CHECK_EQ(32640, result->Int32Value());
15905 
15906  // Make sure that pixel array store ICs clamp values correctly.
15907  result = CompileRun("function pa_store(p) {"
15908  " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15909  "}"
15910  "pa_store(pixels);"
15911  "var sum = 0;"
15912  "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15913  "sum");
15914  CHECK_EQ(48896, result->Int32Value());
15915 
15916  // Make sure that pixel array stores correctly handle accesses outside
15917  // of the pixel array..
15918  result = CompileRun("function pa_store(p,start) {"
15919  " for (var j = 0; j < 256; j++) {"
15920  " p[j+start] = j * 2;"
15921  " }"
15922  "}"
15923  "pa_store(pixels,0);"
15924  "pa_store(pixels,-128);"
15925  "var sum = 0;"
15926  "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15927  "sum");
15928  CHECK_EQ(65280, result->Int32Value());
15929 
15930  // Make sure that the generic store stub correctly handle accesses outside
15931  // of the pixel array..
15932  result = CompileRun("function pa_store(p,start) {"
15933  " for (var j = 0; j < 256; j++) {"
15934  " p[j+start] = j * 2;"
15935  " }"
15936  "}"
15937  "pa_store(pixels,0);"
15938  "just_ints = new Object();"
15939  "for (var i = 0; i < 256; ++i) { just_ints[i] = i; }"
15940  "pa_store(just_ints, 0);"
15941  "pa_store(pixels,-128);"
15942  "var sum = 0;"
15943  "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15944  "sum");
15945  CHECK_EQ(65280, result->Int32Value());
15946 
15947  // Make sure that the generic keyed store stub clamps pixel array values
15948  // correctly.
15949  result = CompileRun("function pa_store(p) {"
15950  " for (var j = 0; j < 256; j++) { p[j] = j * 2; }"
15951  "}"
15952  "pa_store(pixels);"
15953  "just_ints = new Object();"
15954  "pa_store(just_ints);"
15955  "pa_store(pixels);"
15956  "var sum = 0;"
15957  "for (var j = 0; j < 256; j++) { sum += pixels[j]; }"
15958  "sum");
15959  CHECK_EQ(48896, result->Int32Value());
15960 
15961  // Make sure that pixel array loads are optimized by crankshaft.
15962  result = CompileRun("function pa_load(p) {"
15963  " var sum = 0;"
15964  " for (var i=0; i<256; ++i) {"
15965  " sum += p[i];"
15966  " }"
15967  " return sum; "
15968  "}"
15969  "for (var i = 0; i < 256; ++i) { pixels[i] = i; }"
15970  "for (var i = 0; i < 5000; ++i) {"
15971  " result = pa_load(pixels);"
15972  "}"
15973  "result");
15974  CHECK_EQ(32640, result->Int32Value());
15975 
15976  // Make sure that pixel array stores are optimized by crankshaft.
15977  result = CompileRun("function pa_init(p) {"
15978  "for (var i = 0; i < 256; ++i) { p[i] = i; }"
15979  "}"
15980  "function pa_load(p) {"
15981  " var sum = 0;"
15982  " for (var i=0; i<256; ++i) {"
15983  " sum += p[i];"
15984  " }"
15985  " return sum; "
15986  "}"
15987  "for (var i = 0; i < 5000; ++i) {"
15988  " pa_init(pixels);"
15989  "}"
15990  "result = pa_load(pixels);"
15991  "result");
15992  CHECK_EQ(32640, result->Int32Value());
15993 
15994  free(pixel_data);
15995 }
15996 
15997 
15998 THREADED_TEST(PixelArrayInfo) {
15999  LocalContext context;
16000  v8::HandleScope scope(context->GetIsolate());
16001  for (int size = 0; size < 100; size += 10) {
16002  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(size));
16004  obj->SetIndexedPropertiesToPixelData(pixel_data, size);
16006  CHECK_EQ(pixel_data, obj->GetIndexedPropertiesPixelData());
16008  free(pixel_data);
16009  }
16010 }
16011 
16012 
16013 static void NotHandledIndexedPropertyGetter(
16014  uint32_t index,
16017 }
16018 
16019 
16020 static void NotHandledIndexedPropertySetter(
16021  uint32_t index,
16022  Local<Value> value,
16025 }
16026 
16027 
16028 THREADED_TEST(PixelArrayWithInterceptor) {
16029  LocalContext context;
16030  i::Factory* factory = CcTest::i_isolate()->factory();
16031  v8::Isolate* isolate = context->GetIsolate();
16032  v8::HandleScope scope(isolate);
16033  const int kElementCount = 260;
16034  uint8_t* pixel_data = reinterpret_cast<uint8_t*>(malloc(kElementCount));
16037  factory->NewExternalArray(kElementCount,
16039  pixel_data));
16040  for (int i = 0; i < kElementCount; i++) {
16041  pixels->set(i, i % 256);
16042  }
16044  v8::ObjectTemplate::New(context->GetIsolate());
16045  templ->SetIndexedPropertyHandler(NotHandledIndexedPropertyGetter,
16046  NotHandledIndexedPropertySetter);
16047  v8::Handle<v8::Object> obj = templ->NewInstance();
16048  obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
16049  context->Global()->Set(v8_str("pixels"), obj);
16050  v8::Handle<v8::Value> result = CompileRun("pixels[1]");
16051  CHECK_EQ(1, result->Int32Value());
16052  result = CompileRun("var sum = 0;"
16053  "for (var i = 0; i < 8; i++) {"
16054  " sum += pixels[i] = pixels[i] = -i;"
16055  "}"
16056  "sum;");
16057  CHECK_EQ(-28, result->Int32Value());
16058  result = CompileRun("pixels.hasOwnProperty('1')");
16059  CHECK(result->BooleanValue());
16060  free(pixel_data);
16061 }
16062 
16063 
16064 static int ExternalArrayElementSize(v8::ExternalArrayType array_type) {
16065  switch (array_type) {
16069  return 1;
16070  break;
16073  return 2;
16074  break;
16078  return 4;
16079  break;
16081  return 8;
16082  break;
16083  default:
16084  UNREACHABLE();
16085  return -1;
16086  }
16087  UNREACHABLE();
16088  return -1;
16089 }
16090 
16091 
16092 template <class ExternalArrayClass, class ElementType>
16093 static void ObjectWithExternalArrayTestHelper(
16094  Handle<Context> context,
16095  v8::Handle<Object> obj,
16096  int element_count,
16097  v8::ExternalArrayType array_type,
16098  int64_t low, int64_t high) {
16100  i::Isolate* isolate = jsobj->GetIsolate();
16101  obj->Set(v8_str("field"),
16102  v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
16103  context->Global()->Set(v8_str("ext_array"), obj);
16104  v8::Handle<v8::Value> result = CompileRun("ext_array.field");
16105  CHECK_EQ(1503, result->Int32Value());
16106  result = CompileRun("ext_array[1]");
16107  CHECK_EQ(1, result->Int32Value());
16108 
16109  // Check assigned smis
16110  result = CompileRun("for (var i = 0; i < 8; i++) {"
16111  " ext_array[i] = i;"
16112  "}"
16113  "var sum = 0;"
16114  "for (var i = 0; i < 8; i++) {"
16115  " sum += ext_array[i];"
16116  "}"
16117  "sum;");
16118 
16119  CHECK_EQ(28, result->Int32Value());
16120  // Check pass through of assigned smis
16121  result = CompileRun("var sum = 0;"
16122  "for (var i = 0; i < 8; i++) {"
16123  " sum += ext_array[i] = ext_array[i] = -i;"
16124  "}"
16125  "sum;");
16126  CHECK_EQ(-28, result->Int32Value());
16127 
16128 
16129  // Check assigned smis in reverse order
16130  result = CompileRun("for (var i = 8; --i >= 0; ) {"
16131  " ext_array[i] = i;"
16132  "}"
16133  "var sum = 0;"
16134  "for (var i = 0; i < 8; i++) {"
16135  " sum += ext_array[i];"
16136  "}"
16137  "sum;");
16138  CHECK_EQ(28, result->Int32Value());
16139 
16140  // Check pass through of assigned HeapNumbers
16141  result = CompileRun("var sum = 0;"
16142  "for (var i = 0; i < 16; i+=2) {"
16143  " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
16144  "}"
16145  "sum;");
16146  CHECK_EQ(-28, result->Int32Value());
16147 
16148  // Check assigned HeapNumbers
16149  result = CompileRun("for (var i = 0; i < 16; i+=2) {"
16150  " ext_array[i] = (i * 0.5);"
16151  "}"
16152  "var sum = 0;"
16153  "for (var i = 0; i < 16; i+=2) {"
16154  " sum += ext_array[i];"
16155  "}"
16156  "sum;");
16157  CHECK_EQ(28, result->Int32Value());
16158 
16159  // Check assigned HeapNumbers in reverse order
16160  result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
16161  " ext_array[i] = (i * 0.5);"
16162  "}"
16163  "var sum = 0;"
16164  "for (var i = 0; i < 16; i+=2) {"
16165  " sum += ext_array[i];"
16166  "}"
16167  "sum;");
16168  CHECK_EQ(28, result->Int32Value());
16169 
16170  i::ScopedVector<char> test_buf(1024);
16171 
16172  // Check legal boundary conditions.
16173  // The repeated loads and stores ensure the ICs are exercised.
16174  const char* boundary_program =
16175  "var res = 0;"
16176  "for (var i = 0; i < 16; i++) {"
16177  " ext_array[i] = %lld;"
16178  " if (i > 8) {"
16179  " res = ext_array[i];"
16180  " }"
16181  "}"
16182  "res;";
16183  i::OS::SNPrintF(test_buf,
16184  boundary_program,
16185  low);
16186  result = CompileRun(test_buf.start());
16187  CHECK_EQ(low, result->IntegerValue());
16188 
16189  i::OS::SNPrintF(test_buf,
16190  boundary_program,
16191  high);
16192  result = CompileRun(test_buf.start());
16193  CHECK_EQ(high, result->IntegerValue());
16194 
16195  // Check misprediction of type in IC.
16196  result = CompileRun("var tmp_array = ext_array;"
16197  "var sum = 0;"
16198  "for (var i = 0; i < 8; i++) {"
16199  " tmp_array[i] = i;"
16200  " sum += tmp_array[i];"
16201  " if (i == 4) {"
16202  " tmp_array = {};"
16203  " }"
16204  "}"
16205  "sum;");
16206  // Force GC to trigger verification.
16208  CHECK_EQ(28, result->Int32Value());
16209 
16210  // Make sure out-of-range loads do not throw.
16211  i::OS::SNPrintF(test_buf,
16212  "var caught_exception = false;"
16213  "try {"
16214  " ext_array[%d];"
16215  "} catch (e) {"
16216  " caught_exception = true;"
16217  "}"
16218  "caught_exception;",
16219  element_count);
16220  result = CompileRun(test_buf.start());
16221  CHECK_EQ(false, result->BooleanValue());
16222 
16223  // Make sure out-of-range stores do not throw.
16224  i::OS::SNPrintF(test_buf,
16225  "var caught_exception = false;"
16226  "try {"
16227  " ext_array[%d] = 1;"
16228  "} catch (e) {"
16229  " caught_exception = true;"
16230  "}"
16231  "caught_exception;",
16232  element_count);
16233  result = CompileRun(test_buf.start());
16234  CHECK_EQ(false, result->BooleanValue());
16235 
16236  // Check other boundary conditions, values and operations.
16237  result = CompileRun("for (var i = 0; i < 8; i++) {"
16238  " ext_array[7] = undefined;"
16239  "}"
16240  "ext_array[7];");
16241  CHECK_EQ(0, result->Int32Value());
16242  if (array_type == v8::kExternalFloat64Array ||
16243  array_type == v8::kExternalFloat32Array) {
16244  CHECK_EQ(static_cast<int>(i::OS::nan_value()),
16245  static_cast<int>(
16246  i::Object::GetElement(isolate, jsobj, 7)->Number()));
16247  } else {
16248  CheckElementValue(isolate, 0, jsobj, 7);
16249  }
16250 
16251  result = CompileRun("for (var i = 0; i < 8; i++) {"
16252  " ext_array[6] = '2.3';"
16253  "}"
16254  "ext_array[6];");
16255  CHECK_EQ(2, result->Int32Value());
16256  CHECK_EQ(2,
16257  static_cast<int>(
16258  i::Object::GetElement(isolate, jsobj, 6)->Number()));
16259 
16260  if (array_type != v8::kExternalFloat32Array &&
16261  array_type != v8::kExternalFloat64Array) {
16262  // Though the specification doesn't state it, be explicit about
16263  // converting NaNs and +/-Infinity to zero.
16264  result = CompileRun("for (var i = 0; i < 8; i++) {"
16265  " ext_array[i] = 5;"
16266  "}"
16267  "for (var i = 0; i < 8; i++) {"
16268  " ext_array[i] = NaN;"
16269  "}"
16270  "ext_array[5];");
16271  CHECK_EQ(0, result->Int32Value());
16272  CheckElementValue(isolate, 0, jsobj, 5);
16273 
16274  result = CompileRun("for (var i = 0; i < 8; i++) {"
16275  " ext_array[i] = 5;"
16276  "}"
16277  "for (var i = 0; i < 8; i++) {"
16278  " ext_array[i] = Infinity;"
16279  "}"
16280  "ext_array[5];");
16281  int expected_value =
16282  (array_type == v8::kExternalUint8ClampedArray) ? 255 : 0;
16283  CHECK_EQ(expected_value, result->Int32Value());
16284  CheckElementValue(isolate, expected_value, jsobj, 5);
16285 
16286  result = CompileRun("for (var i = 0; i < 8; i++) {"
16287  " ext_array[i] = 5;"
16288  "}"
16289  "for (var i = 0; i < 8; i++) {"
16290  " ext_array[i] = -Infinity;"
16291  "}"
16292  "ext_array[5];");
16293  CHECK_EQ(0, result->Int32Value());
16294  CheckElementValue(isolate, 0, jsobj, 5);
16295 
16296  // Check truncation behavior of integral arrays.
16297  const char* unsigned_data =
16298  "var source_data = [0.6, 10.6];"
16299  "var expected_results = [0, 10];";
16300  const char* signed_data =
16301  "var source_data = [0.6, 10.6, -0.6, -10.6];"
16302  "var expected_results = [0, 10, 0, -10];";
16303  const char* pixel_data =
16304  "var source_data = [0.6, 10.6];"
16305  "var expected_results = [1, 11];";
16306  bool is_unsigned =
16307  (array_type == v8::kExternalUint8Array ||
16308  array_type == v8::kExternalUint16Array ||
16309  array_type == v8::kExternalUint32Array);
16310  bool is_pixel_data = array_type == v8::kExternalUint8ClampedArray;
16311 
16312  i::OS::SNPrintF(test_buf,
16313  "%s"
16314  "var all_passed = true;"
16315  "for (var i = 0; i < source_data.length; i++) {"
16316  " for (var j = 0; j < 8; j++) {"
16317  " ext_array[j] = source_data[i];"
16318  " }"
16319  " all_passed = all_passed &&"
16320  " (ext_array[5] == expected_results[i]);"
16321  "}"
16322  "all_passed;",
16323  (is_unsigned ?
16324  unsigned_data :
16325  (is_pixel_data ? pixel_data : signed_data)));
16326  result = CompileRun(test_buf.start());
16327  CHECK_EQ(true, result->BooleanValue());
16328  }
16329 
16331  ExternalArrayClass::cast(jsobj->elements()));
16332  for (int i = 0; i < element_count; i++) {
16333  array->set(i, static_cast<ElementType>(i));
16334  }
16335 
16336  // Test complex assignments
16337  result = CompileRun("function ee_op_test_complex_func(sum) {"
16338  " for (var i = 0; i < 40; ++i) {"
16339  " sum += (ext_array[i] += 1);"
16340  " sum += (ext_array[i] -= 1);"
16341  " } "
16342  " return sum;"
16343  "}"
16344  "sum=0;"
16345  "for (var i=0;i<10000;++i) {"
16346  " sum=ee_op_test_complex_func(sum);"
16347  "}"
16348  "sum;");
16349  CHECK_EQ(16000000, result->Int32Value());
16350 
16351  // Test count operations
16352  result = CompileRun("function ee_op_test_count_func(sum) {"
16353  " for (var i = 0; i < 40; ++i) {"
16354  " sum += (++ext_array[i]);"
16355  " sum += (--ext_array[i]);"
16356  " } "
16357  " return sum;"
16358  "}"
16359  "sum=0;"
16360  "for (var i=0;i<10000;++i) {"
16361  " sum=ee_op_test_count_func(sum);"
16362  "}"
16363  "sum;");
16364  CHECK_EQ(16000000, result->Int32Value());
16365 
16366  result = CompileRun("ext_array[3] = 33;"
16367  "delete ext_array[3];"
16368  "ext_array[3];");
16369  CHECK_EQ(33, result->Int32Value());
16370 
16371  result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
16372  "ext_array[2] = 12; ext_array[3] = 13;"
16373  "ext_array.__defineGetter__('2',"
16374  "function() { return 120; });"
16375  "ext_array[2];");
16376  CHECK_EQ(12, result->Int32Value());
16377 
16378  result = CompileRun("var js_array = new Array(40);"
16379  "js_array[0] = 77;"
16380  "js_array;");
16381  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16382 
16383  result = CompileRun("ext_array[1] = 23;"
16384  "ext_array.__proto__ = [];"
16385  "js_array.__proto__ = ext_array;"
16386  "js_array.concat(ext_array);");
16387  CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
16388  CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
16389 
16390  result = CompileRun("ext_array[1] = 23;");
16391  CHECK_EQ(23, result->Int32Value());
16392 }
16393 
16394 
16395 template <class FixedTypedArrayClass,
16396  i::ElementsKind elements_kind,
16397  class ElementType>
16398 static void FixedTypedArrayTestHelper(
16399  v8::ExternalArrayType array_type,
16400  ElementType low,
16401  ElementType high) {
16402  i::FLAG_allow_natives_syntax = true;
16403  LocalContext context;
16404  i::Isolate* isolate = CcTest::i_isolate();
16405  i::Factory* factory = isolate->factory();
16406  v8::HandleScope scope(context->GetIsolate());
16407  const int kElementCount = 260;
16408  i::Handle<FixedTypedArrayClass> fixed_array =
16410  factory->NewFixedTypedArray(kElementCount, array_type));
16411  CHECK_EQ(FixedTypedArrayClass::kInstanceType,
16412  fixed_array->map()->instance_type());
16413  CHECK_EQ(kElementCount, fixed_array->length());
16415  for (int i = 0; i < kElementCount; i++) {
16416  fixed_array->set(i, static_cast<ElementType>(i));
16417  }
16418  // Force GC to trigger verification.
16420  for (int i = 0; i < kElementCount; i++) {
16421  CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
16422  static_cast<int64_t>(fixed_array->get_scalar(i)));
16423  }
16426  i::Handle<i::Map> fixed_array_map =
16427  i::JSObject::GetElementsTransitionMap(jsobj, elements_kind);
16428  jsobj->set_map(*fixed_array_map);
16429  jsobj->set_elements(*fixed_array);
16430 
16431  ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
16432  context.local(), obj, kElementCount, array_type,
16433  static_cast<int64_t>(low),
16434  static_cast<int64_t>(high));
16435 }
16436 
16437 
16438 THREADED_TEST(FixedUint8Array) {
16439  FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
16441  0x0, 0xFF);
16442 }
16443 
16444 
16445 THREADED_TEST(FixedUint8ClampedArray) {
16446  FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
16447  i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
16449  0x0, 0xFF);
16450 }
16451 
16452 
16453 THREADED_TEST(FixedInt8Array) {
16454  FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
16456  -0x80, 0x7F);
16457 }
16458 
16459 
16460 THREADED_TEST(FixedUint16Array) {
16461  FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
16463  0x0, 0xFFFF);
16464 }
16465 
16466 
16467 THREADED_TEST(FixedInt16Array) {
16468  FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
16470  -0x8000, 0x7FFF);
16471 }
16472 
16473 
16474 THREADED_TEST(FixedUint32Array) {
16475  FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
16477  0x0, UINT_MAX);
16478 }
16479 
16480 
16481 THREADED_TEST(FixedInt32Array) {
16482  FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
16484  INT_MIN, INT_MAX);
16485 }
16486 
16487 
16488 THREADED_TEST(FixedFloat32Array) {
16489  FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
16491  -500, 500);
16492 }
16493 
16494 
16495 THREADED_TEST(FixedFloat64Array) {
16496  FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
16498  -500, 500);
16499 }
16500 
16501 
16502 template <class ExternalArrayClass, class ElementType>
16503 static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
16504  int64_t low,
16505  int64_t high) {
16506  LocalContext context;
16507  i::Isolate* isolate = CcTest::i_isolate();
16508  i::Factory* factory = isolate->factory();
16509  v8::HandleScope scope(context->GetIsolate());
16510  const int kElementCount = 40;
16511  int element_size = ExternalArrayElementSize(array_type);
16512  ElementType* array_data =
16513  static_cast<ElementType*>(malloc(kElementCount * element_size));
16516  factory->NewExternalArray(kElementCount, array_type, array_data));
16517  // Force GC to trigger verification.
16519  for (int i = 0; i < kElementCount; i++) {
16520  array->set(i, static_cast<ElementType>(i));
16521  }
16522  // Force GC to trigger verification.
16524  for (int i = 0; i < kElementCount; i++) {
16525  CHECK_EQ(static_cast<int64_t>(i),
16526  static_cast<int64_t>(array->get_scalar(i)));
16527  CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(array_data[i]));
16528  }
16529 
16532  // Set the elements to be the external array.
16534  array_type,
16535  kElementCount);
16536  CHECK_EQ(1,
16537  static_cast<int>(
16538  i::Object::GetElement(isolate, jsobj, 1)->Number()));
16539 
16540  ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16541  context.local(), obj, kElementCount, array_type, low, high);
16542 
16543  v8::Handle<v8::Value> result;
16544 
16545  // Test more complex manipulations which cause eax to contain values
16546  // that won't be completely overwritten by loads from the arrays.
16547  // This catches bugs in the instructions used for the KeyedLoadIC
16548  // for byte and word types.
16549  {
16550  const int kXSize = 300;
16551  const int kYSize = 300;
16552  const int kLargeElementCount = kXSize * kYSize * 4;
16553  ElementType* large_array_data =
16554  static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
16555  v8::Handle<v8::Object> large_obj = v8::Object::New(context->GetIsolate());
16556  // Set the elements to be the external array.
16557  large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
16558  array_type,
16559  kLargeElementCount);
16560  context->Global()->Set(v8_str("large_array"), large_obj);
16561  // Initialize contents of a few rows.
16562  for (int x = 0; x < 300; x++) {
16563  int row = 0;
16564  int offset = row * 300 * 4;
16565  large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16566  large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16567  large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16568  large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16569  row = 150;
16570  offset = row * 300 * 4;
16571  large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16572  large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16573  large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16574  large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16575  row = 298;
16576  offset = row * 300 * 4;
16577  large_array_data[offset + 4 * x + 0] = (ElementType) 127;
16578  large_array_data[offset + 4 * x + 1] = (ElementType) 0;
16579  large_array_data[offset + 4 * x + 2] = (ElementType) 0;
16580  large_array_data[offset + 4 * x + 3] = (ElementType) 127;
16581  }
16582  // The goal of the code below is to make "offset" large enough
16583  // that the computation of the index (which goes into eax) has
16584  // high bits set which will not be overwritten by a byte or short
16585  // load.
16586  result = CompileRun("var failed = false;"
16587  "var offset = 0;"
16588  "for (var i = 0; i < 300; i++) {"
16589  " if (large_array[4 * i] != 127 ||"
16590  " large_array[4 * i + 1] != 0 ||"
16591  " large_array[4 * i + 2] != 0 ||"
16592  " large_array[4 * i + 3] != 127) {"
16593  " failed = true;"
16594  " }"
16595  "}"
16596  "offset = 150 * 300 * 4;"
16597  "for (var i = 0; i < 300; i++) {"
16598  " if (large_array[offset + 4 * i] != 127 ||"
16599  " large_array[offset + 4 * i + 1] != 0 ||"
16600  " large_array[offset + 4 * i + 2] != 0 ||"
16601  " large_array[offset + 4 * i + 3] != 127) {"
16602  " failed = true;"
16603  " }"
16604  "}"
16605  "offset = 298 * 300 * 4;"
16606  "for (var i = 0; i < 300; i++) {"
16607  " if (large_array[offset + 4 * i] != 127 ||"
16608  " large_array[offset + 4 * i + 1] != 0 ||"
16609  " large_array[offset + 4 * i + 2] != 0 ||"
16610  " large_array[offset + 4 * i + 3] != 127) {"
16611  " failed = true;"
16612  " }"
16613  "}"
16614  "!failed;");
16615  CHECK_EQ(true, result->BooleanValue());
16616  free(large_array_data);
16617  }
16618 
16619  // The "" property descriptor is overloaded to store information about
16620  // the external array. Ensure that setting and accessing the "" property
16621  // works (it should overwrite the information cached about the external
16622  // array in the DescriptorArray) in various situations.
16623  result = CompileRun("ext_array[''] = 23; ext_array['']");
16624  CHECK_EQ(23, result->Int32Value());
16625 
16626  // Property "" set after the external array is associated with the object.
16627  {
16629  obj2->Set(v8_str("ee_test_field"),
16630  v8::Int32::New(context->GetIsolate(), 256));
16631  obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
16632  // Set the elements to be the external array.
16633  obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16634  array_type,
16635  kElementCount);
16636  context->Global()->Set(v8_str("ext_array"), obj2);
16637  result = CompileRun("ext_array['']");
16638  CHECK_EQ(1503, result->Int32Value());
16639  }
16640 
16641  // Property "" set after the external array is associated with the object.
16642  {
16644  obj2->Set(v8_str("ee_test_field_2"),
16645  v8::Int32::New(context->GetIsolate(), 256));
16646  // Set the elements to be the external array.
16647  obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16648  array_type,
16649  kElementCount);
16650  obj2->Set(v8_str(""), v8::Int32::New(context->GetIsolate(), 1503));
16651  context->Global()->Set(v8_str("ext_array"), obj2);
16652  result = CompileRun("ext_array['']");
16653  CHECK_EQ(1503, result->Int32Value());
16654  }
16655 
16656  // Should reuse the map from previous test.
16657  {
16659  obj2->Set(v8_str("ee_test_field_2"),
16660  v8::Int32::New(context->GetIsolate(), 256));
16661  // Set the elements to be the external array. Should re-use the map
16662  // from previous test.
16663  obj2->SetIndexedPropertiesToExternalArrayData(array_data,
16664  array_type,
16665  kElementCount);
16666  context->Global()->Set(v8_str("ext_array"), obj2);
16667  result = CompileRun("ext_array['']");
16668  }
16669 
16670  // Property "" is a constant function that shouldn't not be interfered with
16671  // when an external array is set.
16672  {
16674  // Start
16675  obj2->Set(v8_str("ee_test_field3"),
16676  v8::Int32::New(context->GetIsolate(), 256));
16677 
16678  // Add a constant function to an object.
16679  context->Global()->Set(v8_str("ext_array"), obj2);
16680  result = CompileRun("ext_array[''] = function() {return 1503;};"
16681  "ext_array['']();");
16682 
16683  // Add an external array transition to the same map that
16684  // has the constant transition.
16686  obj3->Set(v8_str("ee_test_field3"),
16687  v8::Int32::New(context->GetIsolate(), 256));
16688  obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16689  array_type,
16690  kElementCount);
16691  context->Global()->Set(v8_str("ext_array"), obj3);
16692  }
16693 
16694  // If a external array transition is in the map, it should get clobbered
16695  // by a constant function.
16696  {
16697  // Add an external array transition.
16699  obj3->Set(v8_str("ee_test_field4"),
16700  v8::Int32::New(context->GetIsolate(), 256));
16701  obj3->SetIndexedPropertiesToExternalArrayData(array_data,
16702  array_type,
16703  kElementCount);
16704 
16705  // Add a constant function to the same map that just got an external array
16706  // transition.
16708  obj2->Set(v8_str("ee_test_field4"),
16709  v8::Int32::New(context->GetIsolate(), 256));
16710  context->Global()->Set(v8_str("ext_array"), obj2);
16711  result = CompileRun("ext_array[''] = function() {return 1503;};"
16712  "ext_array['']();");
16713  }
16714 
16715  free(array_data);
16716 }
16717 
16718 
16719 THREADED_TEST(ExternalInt8Array) {
16720  ExternalArrayTestHelper<i::ExternalInt8Array, int8_t>(
16722  -128,
16723  127);
16724 }
16725 
16726 
16727 THREADED_TEST(ExternalUint8Array) {
16728  ExternalArrayTestHelper<i::ExternalUint8Array, uint8_t>(
16730  0,
16731  255);
16732 }
16733 
16734 
16735 THREADED_TEST(ExternalUint8ClampedArray) {
16736  ExternalArrayTestHelper<i::ExternalUint8ClampedArray, uint8_t>(
16738  0,
16739  255);
16740 }
16741 
16742 
16743 THREADED_TEST(ExternalInt16Array) {
16744  ExternalArrayTestHelper<i::ExternalInt16Array, int16_t>(
16746  -32768,
16747  32767);
16748 }
16749 
16750 
16751 THREADED_TEST(ExternalUint16Array) {
16752  ExternalArrayTestHelper<i::ExternalUint16Array, uint16_t>(
16754  0,
16755  65535);
16756 }
16757 
16758 
16759 THREADED_TEST(ExternalInt32Array) {
16760  ExternalArrayTestHelper<i::ExternalInt32Array, int32_t>(
16762  INT_MIN, // -2147483648
16763  INT_MAX); // 2147483647
16764 }
16765 
16766 
16767 THREADED_TEST(ExternalUint32Array) {
16768  ExternalArrayTestHelper<i::ExternalUint32Array, uint32_t>(
16770  0,
16771  UINT_MAX); // 4294967295
16772 }
16773 
16774 
16775 THREADED_TEST(ExternalFloat32Array) {
16776  ExternalArrayTestHelper<i::ExternalFloat32Array, float>(
16778  -500,
16779  500);
16780 }
16781 
16782 
16783 THREADED_TEST(ExternalFloat64Array) {
16784  ExternalArrayTestHelper<i::ExternalFloat64Array, double>(
16786  -500,
16787  500);
16788 }
16789 
16790 
16791 THREADED_TEST(ExternalArrays) {
16792  TestExternalInt8Array();
16793  TestExternalUint8Array();
16794  TestExternalInt16Array();
16795  TestExternalUint16Array();
16796  TestExternalInt32Array();
16797  TestExternalUint32Array();
16798  TestExternalFloat32Array();
16799 }
16800 
16801 
16803  LocalContext context;
16804  v8::HandleScope scope(context->GetIsolate());
16805  for (int size = 0; size < 100; size += 10) {
16806  int element_size = ExternalArrayElementSize(array_type);
16807  void* external_data = malloc(size * element_size);
16810  external_data, array_type, size);
16812  CHECK_EQ(external_data, obj->GetIndexedPropertiesExternalArrayData());
16815  free(external_data);
16816  }
16817 }
16818 
16819 
16820 THREADED_TEST(ExternalArrayInfo) {
16830 }
16831 
16832 
16834  v8::ExternalArrayType array_type,
16835  int size) {
16836  v8::Handle<v8::Object> obj = v8::Object::New(isolate);
16838  last_location = last_message = NULL;
16839  obj->SetIndexedPropertiesToExternalArrayData(NULL, array_type, size);
16841  CHECK_NE(NULL, last_location);
16842  CHECK_NE(NULL, last_message);
16843 }
16844 
16845 
16846 TEST(ExternalArrayLimits) {
16847  LocalContext context;
16848  v8::Isolate* isolate = context->GetIsolate();
16849  v8::HandleScope scope(isolate);
16850  ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0x40000000);
16851  ExtArrayLimitsHelper(isolate, v8::kExternalInt8Array, 0xffffffff);
16852  ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0x40000000);
16853  ExtArrayLimitsHelper(isolate, v8::kExternalUint8Array, 0xffffffff);
16854  ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0x40000000);
16855  ExtArrayLimitsHelper(isolate, v8::kExternalInt16Array, 0xffffffff);
16856  ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0x40000000);
16857  ExtArrayLimitsHelper(isolate, v8::kExternalUint16Array, 0xffffffff);
16858  ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0x40000000);
16859  ExtArrayLimitsHelper(isolate, v8::kExternalInt32Array, 0xffffffff);
16860  ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0x40000000);
16861  ExtArrayLimitsHelper(isolate, v8::kExternalUint32Array, 0xffffffff);
16862  ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0x40000000);
16863  ExtArrayLimitsHelper(isolate, v8::kExternalFloat32Array, 0xffffffff);
16864  ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0x40000000);
16865  ExtArrayLimitsHelper(isolate, v8::kExternalFloat64Array, 0xffffffff);
16868 }
16869 
16870 
16871 template <typename ElementType, typename TypedArray,
16872  class ExternalArrayClass>
16874  int64_t low, int64_t high) {
16875  const int kElementCount = 50;
16876 
16877  i::ScopedVector<ElementType> backing_store(kElementCount+2);
16878 
16879  LocalContext env;
16880  v8::Isolate* isolate = env->GetIsolate();
16881  v8::HandleScope handle_scope(isolate);
16882 
16883  Local<v8::ArrayBuffer> ab =
16884  v8::ArrayBuffer::New(isolate, backing_store.start(),
16885  (kElementCount + 2) * sizeof(ElementType));
16886  Local<TypedArray> ta =
16887  TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
16888  CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
16889  CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
16890  CHECK_EQ(2*sizeof(ElementType), static_cast<int>(ta->ByteOffset()));
16891  CHECK_EQ(kElementCount*sizeof(ElementType),
16892  static_cast<int>(ta->ByteLength()));
16893  CHECK_EQ(ab, ta->Buffer());
16894 
16895  ElementType* data = backing_store.start() + 2;
16896  for (int i = 0; i < kElementCount; i++) {
16897  data[i] = static_cast<ElementType>(i);
16898  }
16899 
16900  ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
16901  env.local(), ta, kElementCount, array_type, low, high);
16902 }
16903 
16904 
16905 THREADED_TEST(Uint8Array) {
16906  TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::ExternalUint8Array>(
16907  v8::kExternalUint8Array, 0, 0xFF);
16908 }
16909 
16910 
16911 THREADED_TEST(Int8Array) {
16912  TypedArrayTestHelper<int8_t, v8::Int8Array, i::ExternalInt8Array>(
16913  v8::kExternalInt8Array, -0x80, 0x7F);
16914 }
16915 
16916 
16917 THREADED_TEST(Uint16Array) {
16921  v8::kExternalUint16Array, 0, 0xFFFF);
16922 }
16923 
16924 
16925 THREADED_TEST(Int16Array) {
16926  TypedArrayTestHelper<int16_t, v8::Int16Array, i::ExternalInt16Array>(
16927  v8::kExternalInt16Array, -0x8000, 0x7FFF);
16928 }
16929 
16930 
16931 THREADED_TEST(Uint32Array) {
16932  TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::ExternalUint32Array>(
16933  v8::kExternalUint32Array, 0, UINT_MAX);
16934 }
16935 
16936 
16937 THREADED_TEST(Int32Array) {
16938  TypedArrayTestHelper<int32_t, v8::Int32Array, i::ExternalInt32Array>(
16939  v8::kExternalInt32Array, INT_MIN, INT_MAX);
16940 }
16941 
16942 
16943 THREADED_TEST(Float32Array) {
16944  TypedArrayTestHelper<float, v8::Float32Array, i::ExternalFloat32Array>(
16945  v8::kExternalFloat32Array, -500, 500);
16946 }
16947 
16948 
16949 THREADED_TEST(Float64Array) {
16950  TypedArrayTestHelper<double, v8::Float64Array, i::ExternalFloat64Array>(
16951  v8::kExternalFloat64Array, -500, 500);
16952 }
16953 
16954 
16955 THREADED_TEST(Uint8ClampedArray) {
16956  TypedArrayTestHelper<uint8_t,
16959 }
16960 
16961 
16962 THREADED_TEST(DataView) {
16963  const int kSize = 50;
16964 
16965  i::ScopedVector<uint8_t> backing_store(kSize+2);
16966 
16967  LocalContext env;
16968  v8::Isolate* isolate = env->GetIsolate();
16969  v8::HandleScope handle_scope(isolate);
16970 
16971  Local<v8::ArrayBuffer> ab =
16972  v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
16973  Local<v8::DataView> dv =
16974  v8::DataView::New(ab, 2, kSize);
16975  CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
16976  CHECK_EQ(2, static_cast<int>(dv->ByteOffset()));
16977  CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
16978  CHECK_EQ(ab, dv->Buffer());
16979 }
16980 
16981 
16982 #define IS_ARRAY_BUFFER_VIEW_TEST(View) \
16983  THREADED_TEST(Is##View) { \
16984  LocalContext env; \
16985  v8::Isolate* isolate = env->GetIsolate(); \
16986  v8::HandleScope handle_scope(isolate); \
16987  \
16988  Handle<Value> result = CompileRun( \
16989  "var ab = new ArrayBuffer(128);" \
16990  "new " #View "(ab)"); \
16991  CHECK(result->IsArrayBufferView()); \
16992  CHECK(result->Is##View()); \
16993  CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
16994  }
16995 
16996 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
16997 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
16998 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
16999 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
17000 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
17001 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
17002 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
17003 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
17004 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
17005 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
17006 
17007 #undef IS_ARRAY_BUFFER_VIEW_TEST
17008 
17009 
17010 
17011 THREADED_TEST(ScriptContextDependence) {
17012  LocalContext c1;
17013  v8::HandleScope scope(c1->GetIsolate());
17014  const char *source = "foo";
17015  v8::Handle<v8::Script> dep = v8_compile(source);
17017  c1->GetIsolate(), source));
17019  v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
17020  c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
17021  v8::Integer::New(c1->GetIsolate(), 100));
17022  CHECK_EQ(dep->Run()->Int32Value(), 100);
17023  CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
17024  LocalContext c2;
17025  c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
17026  v8::Integer::New(c2->GetIsolate(), 101));
17027  CHECK_EQ(dep->Run()->Int32Value(), 100);
17028  CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
17029 }
17030 
17031 
17032 THREADED_TEST(StackTrace) {
17033  LocalContext context;
17034  v8::HandleScope scope(context->GetIsolate());
17035  v8::TryCatch try_catch;
17036  const char *source = "function foo() { FAIL.FAIL; }; foo();";
17038  v8::String::NewFromUtf8(context->GetIsolate(), source);
17039  v8::Handle<v8::String> origin =
17040  v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
17041  v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
17042  v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
17043  ->BindToCurrentContext()
17044  ->Run();
17045  CHECK(try_catch.HasCaught());
17046  v8::String::Utf8Value stack(try_catch.StackTrace());
17047  CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
17048 }
17049 
17050 
17051 // Checks that a StackFrame has certain expected values.
17052 void checkStackFrame(const char* expected_script_name,
17053  const char* expected_func_name, int expected_line_number,
17054  int expected_column, bool is_eval, bool is_constructor,
17057  v8::String::Utf8Value func_name(frame->GetFunctionName());
17058  v8::String::Utf8Value script_name(frame->GetScriptName());
17059  if (*script_name == NULL) {
17060  // The situation where there is no associated script, like for evals.
17061  CHECK(expected_script_name == NULL);
17062  } else {
17063  CHECK(strstr(*script_name, expected_script_name) != NULL);
17064  }
17065  CHECK(strstr(*func_name, expected_func_name) != NULL);
17066  CHECK_EQ(expected_line_number, frame->GetLineNumber());
17067  CHECK_EQ(expected_column, frame->GetColumn());
17068  CHECK_EQ(is_eval, frame->IsEval());
17069  CHECK_EQ(is_constructor, frame->IsConstructor());
17070 }
17071 
17072 
17074  v8::HandleScope scope(args.GetIsolate());
17075  const char* origin = "capture-stack-trace-test";
17076  const int kOverviewTest = 1;
17077  const int kDetailedTest = 2;
17078 
17079  ASSERT(args.Length() == 1);
17080 
17081  int testGroup = args[0]->Int32Value();
17082  if (testGroup == kOverviewTest) {
17085  CHECK_EQ(4, stackTrace->GetFrameCount());
17086  checkStackFrame(origin, "bar", 2, 10, false, false,
17087  stackTrace->GetFrame(0));
17088  checkStackFrame(origin, "foo", 6, 3, false, false,
17089  stackTrace->GetFrame(1));
17090  // This is the source string inside the eval which has the call to foo.
17091  checkStackFrame(NULL, "", 1, 5, false, false,
17092  stackTrace->GetFrame(2));
17093  // The last frame is an anonymous function which has the initial eval call.
17094  checkStackFrame(origin, "", 8, 7, false, false,
17095  stackTrace->GetFrame(3));
17096 
17097  CHECK(stackTrace->AsArray()->IsArray());
17098  } else if (testGroup == kDetailedTest) {
17101  CHECK_EQ(4, stackTrace->GetFrameCount());
17102  checkStackFrame(origin, "bat", 4, 22, false, false,
17103  stackTrace->GetFrame(0));
17104  checkStackFrame(origin, "baz", 8, 3, false, true,
17105  stackTrace->GetFrame(1));
17106 #ifdef ENABLE_DEBUGGER_SUPPORT
17107  bool is_eval = true;
17108 #else // ENABLE_DEBUGGER_SUPPORT
17109  bool is_eval = false;
17110 #endif // ENABLE_DEBUGGER_SUPPORT
17111 
17112  // This is the source string inside the eval which has the call to baz.
17113  checkStackFrame(NULL, "", 1, 5, is_eval, false,
17114  stackTrace->GetFrame(2));
17115  // The last frame is an anonymous function which has the initial eval call.
17116  checkStackFrame(origin, "", 10, 1, false, false,
17117  stackTrace->GetFrame(3));
17118 
17119  CHECK(stackTrace->AsArray()->IsArray());
17120  }
17121 }
17122 
17123 
17124 // Tests the C++ StackTrace API.
17125 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
17126 // THREADED_TEST(CaptureStackTrace) {
17127 TEST(CaptureStackTrace) {
17128  v8::Isolate* isolate = CcTest::isolate();
17129  v8::HandleScope scope(isolate);
17130  v8::Handle<v8::String> origin =
17131  v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
17132  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17133  templ->Set(v8_str("AnalyzeStackInNativeCode"),
17135  LocalContext context(0, templ);
17136 
17137  // Test getting OVERVIEW information. Should ignore information that is not
17138  // script name, function name, line number, and column offset.
17139  const char *overview_source =
17140  "function bar() {\n"
17141  " var y; AnalyzeStackInNativeCode(1);\n"
17142  "}\n"
17143  "function foo() {\n"
17144  "\n"
17145  " bar();\n"
17146  "}\n"
17147  "var x;eval('new foo();');";
17148  v8::Handle<v8::String> overview_src =
17149  v8::String::NewFromUtf8(isolate, overview_source);
17150  v8::ScriptCompiler::Source script_source(overview_src,
17151  v8::ScriptOrigin(origin));
17152  v8::Handle<Value> overview_result(
17153  v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
17154  ->BindToCurrentContext()
17155  ->Run());
17156  CHECK(!overview_result.IsEmpty());
17157  CHECK(overview_result->IsObject());
17158 
17159  // Test getting DETAILED information.
17160  const char *detailed_source =
17161  "function bat() {AnalyzeStackInNativeCode(2);\n"
17162  "}\n"
17163  "\n"
17164  "function baz() {\n"
17165  " bat();\n"
17166  "}\n"
17167  "eval('new baz();');";
17168  v8::Handle<v8::String> detailed_src =
17169  v8::String::NewFromUtf8(isolate, detailed_source);
17170  // Make the script using a non-zero line and column offset.
17171  v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
17172  v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
17173  v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
17174  v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
17175  v8::Handle<v8::UnboundScript> detailed_script(
17176  v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
17177  v8::Handle<Value> detailed_result(
17178  detailed_script->BindToCurrentContext()->Run());
17179  CHECK(!detailed_result.IsEmpty());
17180  CHECK(detailed_result->IsObject());
17181 }
17182 
17183 
17184 static void StackTraceForUncaughtExceptionListener(
17185  v8::Handle<v8::Message> message,
17187  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17188  CHECK_EQ(2, stack_trace->GetFrameCount());
17189  checkStackFrame("origin", "foo", 2, 3, false, false,
17190  stack_trace->GetFrame(0));
17191  checkStackFrame("origin", "bar", 5, 3, false, false,
17192  stack_trace->GetFrame(1));
17193 }
17194 
17195 
17196 TEST(CaptureStackTraceForUncaughtException) {
17197  report_count = 0;
17198  LocalContext env;
17199  v8::HandleScope scope(env->GetIsolate());
17200  v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
17202 
17203  CompileRunWithOrigin(
17204  "function foo() {\n"
17205  " throw 1;\n"
17206  "};\n"
17207  "function bar() {\n"
17208  " foo();\n"
17209  "};",
17210  "origin");
17211  v8::Local<v8::Object> global = env->Global();
17212  Local<Value> trouble = global->Get(v8_str("bar"));
17213  CHECK(trouble->IsFunction());
17214  Function::Cast(*trouble)->Call(global, 0, NULL);
17216  v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
17217 }
17218 
17219 
17220 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
17221  LocalContext env;
17222  v8::HandleScope scope(env->GetIsolate());
17224  1024,
17226 
17227  CompileRun(
17228  "var setters = ['column', 'lineNumber', 'scriptName',\n"
17229  " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
17230  " 'isConstructor'];\n"
17231  "for (var i = 0; i < setters.length; i++) {\n"
17232  " var prop = setters[i];\n"
17233  " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
17234  "}\n");
17235  CompileRun("throw 'exception';");
17237 }
17238 
17239 
17240 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
17241  v8::Handle<v8::Value> data) {
17242  // Use the frame where JavaScript is called from.
17243  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17244  CHECK(!stack_trace.IsEmpty());
17245  int frame_count = stack_trace->GetFrameCount();
17246  CHECK_EQ(3, frame_count);
17247  int line_number[] = {1, 2, 5};
17248  for (int i = 0; i < frame_count; i++) {
17249  CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17250  }
17251 }
17252 
17253 
17254 // Test that we only return the stack trace at the site where the exception
17255 // is first thrown (not where it is rethrown).
17256 TEST(RethrowStackTrace) {
17257  LocalContext env;
17258  v8::HandleScope scope(env->GetIsolate());
17259  // We make sure that
17260  // - the stack trace of the ReferenceError in g() is reported.
17261  // - the stack trace is not overwritten when e1 is rethrown by t().
17262  // - the stack trace of e2 does not overwrite that of e1.
17263  const char* source =
17264  "function g() { error; } \n"
17265  "function f() { g(); } \n"
17266  "function t(e) { throw e; } \n"
17267  "try { \n"
17268  " f(); \n"
17269  "} catch (e1) { \n"
17270  " try { \n"
17271  " error; \n"
17272  " } catch (e2) { \n"
17273  " t(e1); \n"
17274  " } \n"
17275  "} \n";
17276  v8::V8::AddMessageListener(RethrowStackTraceHandler);
17278  CompileRun(source);
17280  v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
17281 }
17282 
17283 
17284 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
17285  v8::Handle<v8::Value> data) {
17286  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17287  CHECK(!stack_trace.IsEmpty());
17288  int frame_count = stack_trace->GetFrameCount();
17289  CHECK_EQ(2, frame_count);
17290  int line_number[] = {3, 7};
17291  for (int i = 0; i < frame_count; i++) {
17292  CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
17293  }
17294 }
17295 
17296 
17297 // Test that we do not recognize identity for primitive exceptions.
17298 TEST(RethrowPrimitiveStackTrace) {
17299  LocalContext env;
17300  v8::HandleScope scope(env->GetIsolate());
17301  // We do not capture stack trace for non Error objects on creation time.
17302  // Instead, we capture the stack trace on last throw.
17303  const char* source =
17304  "function g() { throw 404; } \n"
17305  "function f() { g(); } \n"
17306  "function t(e) { throw e; } \n"
17307  "try { \n"
17308  " f(); \n"
17309  "} catch (e1) { \n"
17310  " t(e1) \n"
17311  "} \n";
17312  v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
17314  CompileRun(source);
17316  v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
17317 }
17318 
17319 
17320 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
17321  v8::Handle<v8::Value> data) {
17322  // Use the frame where JavaScript is called from.
17323  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17324  CHECK(!stack_trace.IsEmpty());
17325  CHECK_EQ(1, stack_trace->GetFrameCount());
17326  CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
17327 }
17328 
17329 
17330 // Test that the stack trace is captured when the error object is created and
17331 // not where it is thrown.
17332 TEST(RethrowExistingStackTrace) {
17333  LocalContext env;
17334  v8::HandleScope scope(env->GetIsolate());
17335  const char* source =
17336  "var e = new Error(); \n"
17337  "throw e; \n";
17338  v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
17340  CompileRun(source);
17342  v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
17343 }
17344 
17345 
17346 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
17347  v8::Handle<v8::Value> data) {
17348  // Use the frame where JavaScript is called from.
17349  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
17350  CHECK(!stack_trace.IsEmpty());
17351  CHECK_EQ(1, stack_trace->GetFrameCount());
17352  CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
17353 }
17354 
17355 
17356 // Test that the stack trace is captured where the bogus Error object is thrown.
17357 TEST(RethrowBogusErrorStackTrace) {
17358  LocalContext env;
17359  v8::HandleScope scope(env->GetIsolate());
17360  const char* source =
17361  "var e = {__proto__: new Error()} \n"
17362  "throw e; \n";
17363  v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
17365  CompileRun(source);
17367  v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
17368 }
17369 
17370 
17373  v8::HandleScope scope(args.GetIsolate());
17376  CHECK_EQ(5, stackTrace->GetFrameCount());
17377  v8::Handle<v8::String> url = v8_str("eval_url");
17378  for (int i = 0; i < 3; i++) {
17379  v8::Handle<v8::String> name =
17380  stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17381  CHECK(!name.IsEmpty());
17382  CHECK_EQ(url, name);
17383  }
17384 }
17385 
17386 
17387 TEST(SourceURLInStackTrace) {
17388  v8::Isolate* isolate = CcTest::isolate();
17389  v8::HandleScope scope(isolate);
17390  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17391  templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
17392  v8::FunctionTemplate::New(isolate,
17394  LocalContext context(0, templ);
17395 
17396  const char *source =
17397  "function outer() {\n"
17398  "function bar() {\n"
17399  " AnalyzeStackOfEvalWithSourceURL();\n"
17400  "}\n"
17401  "function foo() {\n"
17402  "\n"
17403  " bar();\n"
17404  "}\n"
17405  "foo();\n"
17406  "}\n"
17407  "eval('(' + outer +')()%s');";
17408 
17410  i::OS::SNPrintF(code, source, "//# sourceURL=eval_url");
17411  CHECK(CompileRun(code.start())->IsUndefined());
17412  i::OS::SNPrintF(code, source, "//@ sourceURL=eval_url");
17413  CHECK(CompileRun(code.start())->IsUndefined());
17414 }
17415 
17416 
17417 static int scriptIdInStack[2];
17418 
17421  v8::HandleScope scope(args.GetIsolate());
17424  CHECK_EQ(2, stackTrace->GetFrameCount());
17425  for (int i = 0; i < 2; i++) {
17426  scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
17427  }
17428 }
17429 
17430 
17431 TEST(ScriptIdInStackTrace) {
17432  v8::Isolate* isolate = CcTest::isolate();
17433  v8::HandleScope scope(isolate);
17434  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17435  templ->Set(v8_str("AnalyzeScriptIdInStack"),
17437  LocalContext context(0, templ);
17438 
17440  isolate,
17441  "function foo() {\n"
17442  " AnalyzeScriptIdInStack();"
17443  "}\n"
17444  "foo();\n");
17445  v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
17446  script->Run();
17447  for (int i = 0; i < 2; i++) {
17448  CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
17449  CHECK_EQ(scriptIdInStack[i], script->GetId());
17450  }
17451 }
17452 
17453 
17456  v8::HandleScope scope(args.GetIsolate());
17459  CHECK_EQ(4, stackTrace->GetFrameCount());
17460  v8::Handle<v8::String> url = v8_str("url");
17461  for (int i = 0; i < 3; i++) {
17462  v8::Handle<v8::String> name =
17463  stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17464  CHECK(!name.IsEmpty());
17465  CHECK_EQ(url, name);
17466  }
17467 }
17468 
17469 
17470 TEST(InlineScriptWithSourceURLInStackTrace) {
17471  v8::Isolate* isolate = CcTest::isolate();
17472  v8::HandleScope scope(isolate);
17473  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17474  templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
17477  LocalContext context(0, templ);
17478 
17479  const char *source =
17480  "function outer() {\n"
17481  "function bar() {\n"
17482  " AnalyzeStackOfInlineScriptWithSourceURL();\n"
17483  "}\n"
17484  "function foo() {\n"
17485  "\n"
17486  " bar();\n"
17487  "}\n"
17488  "foo();\n"
17489  "}\n"
17490  "outer()\n%s";
17491 
17493  i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17494  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17495  i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17496  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
17497 }
17498 
17499 
17502  v8::HandleScope scope(args.GetIsolate());
17505  CHECK_EQ(4, stackTrace->GetFrameCount());
17506  v8::Handle<v8::String> url = v8_str("source_url");
17507  for (int i = 0; i < 3; i++) {
17508  v8::Handle<v8::String> name =
17509  stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
17510  CHECK(!name.IsEmpty());
17511  CHECK_EQ(url, name);
17512  }
17513 }
17514 
17515 
17516 TEST(DynamicWithSourceURLInStackTrace) {
17517  v8::Isolate* isolate = CcTest::isolate();
17518  v8::HandleScope scope(isolate);
17519  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17520  templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
17523  LocalContext context(0, templ);
17524 
17525  const char *source =
17526  "function outer() {\n"
17527  "function bar() {\n"
17528  " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
17529  "}\n"
17530  "function foo() {\n"
17531  "\n"
17532  " bar();\n"
17533  "}\n"
17534  "foo();\n"
17535  "}\n"
17536  "outer()\n%s";
17537 
17539  i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17540  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17541  i::OS::SNPrintF(code, source, "//@ sourceURL=source_url");
17542  CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
17543 }
17544 
17545 
17546 TEST(DynamicWithSourceURLInStackTraceString) {
17547  LocalContext context;
17548  v8::HandleScope scope(context->GetIsolate());
17549 
17550  const char *source =
17551  "function outer() {\n"
17552  " function foo() {\n"
17553  " FAIL.FAIL;\n"
17554  " }\n"
17555  " foo();\n"
17556  "}\n"
17557  "outer()\n%s";
17558 
17560  i::OS::SNPrintF(code, source, "//# sourceURL=source_url");
17561  v8::TryCatch try_catch;
17562  CompileRunWithOrigin(code.start(), "", 0, 0);
17563  CHECK(try_catch.HasCaught());
17564  v8::String::Utf8Value stack(try_catch.StackTrace());
17565  CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
17566 }
17567 
17568 
17569 static void CreateGarbageInOldSpace() {
17570  i::Factory* factory = CcTest::i_isolate()->factory();
17572  i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
17573  for (int i = 0; i < 1000; i++) {
17574  factory->NewFixedArray(1000, i::TENURED);
17575  }
17576 }
17577 
17578 
17579 // Test that idle notification can be handled and eventually returns true.
17580 TEST(IdleNotification) {
17581  const intptr_t MB = 1024 * 1024;
17582  LocalContext env;
17583  v8::HandleScope scope(env->GetIsolate());
17584  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17585  CreateGarbageInOldSpace();
17586  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17587  CHECK_GT(size_with_garbage, initial_size + MB);
17588  bool finished = false;
17589  for (int i = 0; i < 200 && !finished; i++) {
17590  finished = v8::V8::IdleNotification();
17591  }
17592  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17593  CHECK(finished);
17594  CHECK_LT(final_size, initial_size + 1);
17595 }
17596 
17597 
17598 // Test that idle notification can be handled and eventually collects garbage.
17599 TEST(IdleNotificationWithSmallHint) {
17600  const intptr_t MB = 1024 * 1024;
17601  const int IdlePauseInMs = 900;
17602  LocalContext env;
17603  v8::HandleScope scope(env->GetIsolate());
17604  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17605  CreateGarbageInOldSpace();
17606  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17607  CHECK_GT(size_with_garbage, initial_size + MB);
17608  bool finished = false;
17609  for (int i = 0; i < 200 && !finished; i++) {
17610  finished = v8::V8::IdleNotification(IdlePauseInMs);
17611  }
17612  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17613  CHECK(finished);
17614  CHECK_LT(final_size, initial_size + 1);
17615 }
17616 
17617 
17618 // Test that idle notification can be handled and eventually collects garbage.
17619 TEST(IdleNotificationWithLargeHint) {
17620  const intptr_t MB = 1024 * 1024;
17621  const int IdlePauseInMs = 900;
17622  LocalContext env;
17623  v8::HandleScope scope(env->GetIsolate());
17624  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17625  CreateGarbageInOldSpace();
17626  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17627  CHECK_GT(size_with_garbage, initial_size + MB);
17628  bool finished = false;
17629  for (int i = 0; i < 200 && !finished; i++) {
17630  finished = v8::V8::IdleNotification(IdlePauseInMs);
17631  }
17632  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17633  CHECK(finished);
17634  CHECK_LT(final_size, initial_size + 1);
17635 }
17636 
17637 
17638 TEST(Regress2107) {
17639  const intptr_t MB = 1024 * 1024;
17640  const int kShortIdlePauseInMs = 100;
17641  const int kLongIdlePauseInMs = 1000;
17642  LocalContext env;
17643  v8::Isolate* isolate = env->GetIsolate();
17644  v8::HandleScope scope(env->GetIsolate());
17645  intptr_t initial_size = CcTest::heap()->SizeOfObjects();
17646  // Send idle notification to start a round of incremental GCs.
17647  v8::V8::IdleNotification(kShortIdlePauseInMs);
17648  // Emulate 7 page reloads.
17649  for (int i = 0; i < 7; i++) {
17650  {
17651  v8::HandleScope inner_scope(env->GetIsolate());
17653  ctx->Enter();
17654  CreateGarbageInOldSpace();
17655  ctx->Exit();
17656  }
17658  v8::V8::IdleNotification(kLongIdlePauseInMs);
17659  }
17660  // Create garbage and check that idle notification still collects it.
17661  CreateGarbageInOldSpace();
17662  intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
17663  CHECK_GT(size_with_garbage, initial_size + MB);
17664  bool finished = false;
17665  for (int i = 0; i < 200 && !finished; i++) {
17666  finished = v8::V8::IdleNotification(kShortIdlePauseInMs);
17667  }
17668  intptr_t final_size = CcTest::heap()->SizeOfObjects();
17669  CHECK_LT(final_size, initial_size + 1);
17670 }
17671 
17672 
17673 TEST(Regress2333) {
17674  LocalContext env;
17675  for (int i = 0; i < 3; i++) {
17677  }
17678 }
17679 
17680 static uint32_t* stack_limit;
17681 
17682 static void GetStackLimitCallback(
17684  stack_limit = reinterpret_cast<uint32_t*>(
17686 }
17687 
17688 
17689 // Uses the address of a local variable to determine the stack top now.
17690 // Given a size, returns an address that is that far from the current
17691 // top of stack.
17692 static uint32_t* ComputeStackLimit(uint32_t size) {
17693  uint32_t* answer = &size - (size / sizeof(size));
17694  // If the size is very large and the stack is very near the bottom of
17695  // memory then the calculation above may wrap around and give an address
17696  // that is above the (downwards-growing) stack. In that case we return
17697  // a very low address.
17698  if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
17699  return answer;
17700 }
17701 
17702 
17703 // We need at least 165kB for an x64 debug build with clang and ASAN.
17704 static const int stack_breathing_room = 256 * i::KB;
17705 
17706 
17708  uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
17709 
17710  // Set stack limit.
17711  v8::ResourceConstraints constraints;
17712  constraints.set_stack_limit(set_limit);
17714 
17715  // Execute a script.
17716  LocalContext env;
17717  v8::HandleScope scope(env->GetIsolate());
17718  Local<v8::FunctionTemplate> fun_templ =
17719  v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
17720  Local<Function> fun = fun_templ->GetFunction();
17721  env->Global()->Set(v8_str("get_stack_limit"), fun);
17722  CompileRun("get_stack_limit();");
17723 
17724  CHECK(stack_limit == set_limit);
17725 }
17726 
17727 
17728 TEST(SetResourceConstraintsInThread) {
17729  uint32_t* set_limit;
17730  {
17731  v8::Locker locker(CcTest::isolate());
17732  set_limit = ComputeStackLimit(stack_breathing_room);
17733 
17734  // Set stack limit.
17735  v8::ResourceConstraints constraints;
17736  constraints.set_stack_limit(set_limit);
17738 
17739  // Execute a script.
17741  LocalContext env;
17742  Local<v8::FunctionTemplate> fun_templ =
17743  v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
17744  Local<Function> fun = fun_templ->GetFunction();
17745  env->Global()->Set(v8_str("get_stack_limit"), fun);
17746  CompileRun("get_stack_limit();");
17747 
17748  CHECK(stack_limit == set_limit);
17749  }
17750  {
17751  v8::Locker locker(CcTest::isolate());
17752  CHECK(stack_limit == set_limit);
17753  }
17754 }
17755 
17756 
17757 THREADED_TEST(GetHeapStatistics) {
17758  LocalContext c1;
17759  v8::HandleScope scope(c1->GetIsolate());
17760  v8::HeapStatistics heap_statistics;
17761  CHECK_EQ(static_cast<int>(heap_statistics.total_heap_size()), 0);
17762  CHECK_EQ(static_cast<int>(heap_statistics.used_heap_size()), 0);
17763  c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
17764  CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
17765  CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
17766 }
17767 
17768 
17770  public:
17771  explicit VisitorImpl(TestResource** resource) {
17772  for (int i = 0; i < 4; i++) {
17773  resource_[i] = resource[i];
17774  found_resource_[i] = false;
17775  }
17776  }
17777  virtual ~VisitorImpl() {}
17779  if (!string->IsExternal()) {
17780  CHECK(string->IsExternalAscii());
17781  return;
17782  }
17784  string->GetExternalStringResource();
17785  CHECK(resource);
17786  for (int i = 0; i < 4; i++) {
17787  if (resource_[i] == resource) {
17788  CHECK(!found_resource_[i]);
17789  found_resource_[i] = true;
17790  }
17791  }
17792  }
17794  for (int i = 0; i < 4; i++) {
17795  CHECK(found_resource_[i]);
17796  }
17797  }
17798 
17799  private:
17800  v8::String::ExternalStringResource* resource_[4];
17801  bool found_resource_[4];
17802 };
17803 
17804 
17805 TEST(ExternalizeOldSpaceTwoByteCons) {
17806  LocalContext env;
17807  v8::HandleScope scope(env->GetIsolate());
17808  v8::Local<v8::String> cons =
17809  CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
17810  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17812  CHECK(CcTest::heap()->old_pointer_space()->Contains(
17813  *v8::Utils::OpenHandle(*cons)));
17814 
17815  TestResource* resource = new TestResource(
17816  AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
17817  cons->MakeExternal(resource);
17818 
17819  CHECK(cons->IsExternal());
17820  CHECK_EQ(resource, cons->GetExternalStringResource());
17821  String::Encoding encoding;
17822  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17823  CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
17824 }
17825 
17826 
17827 TEST(ExternalizeOldSpaceOneByteCons) {
17828  LocalContext env;
17829  v8::HandleScope scope(env->GetIsolate());
17830  v8::Local<v8::String> cons =
17831  CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString();
17832  CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
17834  CHECK(CcTest::heap()->old_pointer_space()->Contains(
17835  *v8::Utils::OpenHandle(*cons)));
17836 
17837  TestAsciiResource* resource =
17838  new TestAsciiResource(i::StrDup("Romeo Montague Juliet Capulet"));
17839  cons->MakeExternal(resource);
17840 
17841  CHECK(cons->IsExternalAscii());
17842  CHECK_EQ(resource, cons->GetExternalAsciiStringResource());
17843  String::Encoding encoding;
17844  CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
17845  CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
17846 }
17847 
17848 
17849 TEST(VisitExternalStrings) {
17850  LocalContext env;
17851  v8::HandleScope scope(env->GetIsolate());
17852  const char* string = "Some string";
17853  uint16_t* two_byte_string = AsciiToTwoByteString(string);
17854  TestResource* resource[4];
17855  resource[0] = new TestResource(two_byte_string);
17856  v8::Local<v8::String> string0 =
17857  v8::String::NewExternal(env->GetIsolate(), resource[0]);
17858  resource[1] = new TestResource(two_byte_string, NULL, false);
17859  v8::Local<v8::String> string1 =
17860  v8::String::NewExternal(env->GetIsolate(), resource[1]);
17861 
17862  // Externalized symbol.
17863  resource[2] = new TestResource(two_byte_string, NULL, false);
17866  CHECK(string2->MakeExternal(resource[2]));
17867 
17868  // Symbolized External.
17869  resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
17870  v8::Local<v8::String> string3 =
17871  v8::String::NewExternal(env->GetIsolate(), resource[3]);
17872  CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
17873  // Turn into a symbol.
17874  i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
17875  CHECK(!CcTest::heap()->InternalizeString(*string3_i)->IsFailure());
17876  CHECK(string3_i->IsInternalizedString());
17877 
17878  // We need to add usages for string* to avoid warnings in GCC 4.7
17879  CHECK(string0->IsExternal());
17880  CHECK(string1->IsExternal());
17881  CHECK(string2->IsExternal());
17882  CHECK(string3->IsExternal());
17883 
17884  VisitorImpl visitor(resource);
17886  visitor.CheckVisitedResources();
17887 }
17888 
17889 
17890 TEST(ExternalStringCollectedAtTearDown) {
17891  int destroyed = 0;
17892  v8::Isolate* isolate = v8::Isolate::New();
17893  { v8::Isolate::Scope isolate_scope(isolate);
17894  v8::HandleScope handle_scope(isolate);
17895  const char* s = "One string to test them all, one string to find them.";
17896  TestAsciiResource* inscription =
17897  new TestAsciiResource(i::StrDup(s), &destroyed);
17898  v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
17899  // Ring is still alive. Orcs are roaming freely across our lands.
17900  CHECK_EQ(0, destroyed);
17901  USE(ring);
17902  }
17903 
17904  isolate->Dispose();
17905  // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17906  CHECK_EQ(1, destroyed);
17907 }
17908 
17909 
17910 TEST(ExternalInternalizedStringCollectedAtTearDown) {
17911  int destroyed = 0;
17912  v8::Isolate* isolate = v8::Isolate::New();
17913  { v8::Isolate::Scope isolate_scope(isolate);
17914  LocalContext env(isolate);
17915  v8::HandleScope handle_scope(isolate);
17916  CompileRun("var ring = 'One string to test them all';");
17917  const char* s = "One string to test them all";
17918  TestAsciiResource* inscription =
17919  new TestAsciiResource(i::StrDup(s), &destroyed);
17920  v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17921  CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17922  ring->MakeExternal(inscription);
17923  // Ring is still alive. Orcs are roaming freely across our lands.
17924  CHECK_EQ(0, destroyed);
17925  USE(ring);
17926  }
17927 
17928  isolate->Dispose();
17929  // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17930  CHECK_EQ(1, destroyed);
17931 }
17932 
17933 
17934 TEST(ExternalInternalizedStringCollectedAtGC) {
17935  int destroyed = 0;
17936  { LocalContext env;
17937  v8::HandleScope handle_scope(env->GetIsolate());
17938  CompileRun("var ring = 'One string to test them all';");
17939  const char* s = "One string to test them all";
17940  TestAsciiResource* inscription =
17941  new TestAsciiResource(i::StrDup(s), &destroyed);
17942  v8::Local<v8::String> ring = CompileRun("ring")->ToString();
17943  CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
17944  ring->MakeExternal(inscription);
17945  // Ring is still alive. Orcs are roaming freely across our lands.
17946  CHECK_EQ(0, destroyed);
17947  USE(ring);
17948  }
17949 
17950  // Garbage collector deals swift blows to evil.
17953 
17954  // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
17955  CHECK_EQ(1, destroyed);
17956 }
17957 
17958 
17959 static double DoubleFromBits(uint64_t value) {
17960  double target;
17961  i::OS::MemCopy(&target, &value, sizeof(target));
17962  return target;
17963 }
17964 
17965 
17966 static uint64_t DoubleToBits(double value) {
17967  uint64_t target;
17968  i::OS::MemCopy(&target, &value, sizeof(target));
17969  return target;
17970 }
17971 
17972 
17973 static double DoubleToDateTime(double input) {
17974  double date_limit = 864e13;
17975  if (std::isnan(input) || input < -date_limit || input > date_limit) {
17976  return i::OS::nan_value();
17977  }
17978  return (input < 0) ? -(std::floor(-input)) : std::floor(input);
17979 }
17980 
17981 
17982 // We don't have a consistent way to write 64-bit constants syntactically, so we
17983 // split them into two 32-bit constants and combine them programmatically.
17984 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
17985  return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
17986 }
17987 
17988 
17989 THREADED_TEST(QuietSignalingNaNs) {
17990  LocalContext context;
17991  v8::Isolate* isolate = context->GetIsolate();
17992  v8::HandleScope scope(isolate);
17993  v8::TryCatch try_catch;
17994 
17995  // Special double values.
17996  double snan = DoubleFromBits(0x7ff00000, 0x00000001);
17997  double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
17998  double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
17999  double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
18000  double min_normal = DoubleFromBits(0x00100000, 0x00000000);
18001  double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
18002  double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
18003 
18004  // Date values are capped at +/-100000000 days (times 864e5 ms per day)
18005  // on either side of the epoch.
18006  double date_limit = 864e13;
18007 
18008  double test_values[] = {
18009  snan,
18010  qnan,
18011  infinity,
18012  max_normal,
18013  date_limit + 1,
18014  date_limit,
18015  min_normal,
18016  max_denormal,
18017  min_denormal,
18018  0,
18019  -0,
18020  -min_denormal,
18021  -max_denormal,
18022  -min_normal,
18023  -date_limit,
18024  -date_limit - 1,
18025  -max_normal,
18026  -infinity,
18027  -qnan,
18028  -snan
18029  };
18030  int num_test_values = 20;
18031 
18032  for (int i = 0; i < num_test_values; i++) {
18033  double test_value = test_values[i];
18034 
18035  // Check that Number::New preserves non-NaNs and quiets SNaNs.
18036  v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
18037  double stored_number = number->NumberValue();
18038  if (!std::isnan(test_value)) {
18039  CHECK_EQ(test_value, stored_number);
18040  } else {
18041  uint64_t stored_bits = DoubleToBits(stored_number);
18042  // Check if quiet nan (bits 51..62 all set).
18043 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
18044  // Most significant fraction bit for quiet nan is set to 0
18045  // on MIPS architecture. Allowed by IEEE-754.
18046  CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18047 #else
18048  CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
18049 #endif
18050  }
18051 
18052  // Check that Date::New preserves non-NaNs in the date range and
18053  // quiets SNaNs.
18054  v8::Handle<v8::Value> date =
18055  v8::Date::New(isolate, test_value);
18056  double expected_stored_date = DoubleToDateTime(test_value);
18057  double stored_date = date->NumberValue();
18058  if (!std::isnan(expected_stored_date)) {
18059  CHECK_EQ(expected_stored_date, stored_date);
18060  } else {
18061  uint64_t stored_bits = DoubleToBits(stored_date);
18062  // Check if quiet nan (bits 51..62 all set).
18063 #if defined(V8_TARGET_ARCH_MIPS) && !defined(USE_SIMULATOR)
18064  // Most significant fraction bit for quiet nan is set to 0
18065  // on MIPS architecture. Allowed by IEEE-754.
18066  CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
18067 #else
18068  CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
18069 #endif
18070  }
18071  }
18072 }
18073 
18074 
18075 static void SpaghettiIncident(
18077  v8::HandleScope scope(args.GetIsolate());
18078  v8::TryCatch tc;
18079  v8::Handle<v8::String> str(args[0]->ToString());
18080  USE(str);
18081  if (tc.HasCaught())
18082  tc.ReThrow();
18083 }
18084 
18085 
18086 // Test that an exception can be propagated down through a spaghetti
18087 // stack using ReThrow.
18088 THREADED_TEST(SpaghettiStackReThrow) {
18089  v8::Isolate* isolate = CcTest::isolate();
18090  v8::HandleScope scope(isolate);
18091  LocalContext context;
18092  context->Global()->Set(
18093  v8::String::NewFromUtf8(isolate, "s"),
18094  v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
18095  v8::TryCatch try_catch;
18096  CompileRun(
18097  "var i = 0;"
18098  "var o = {"
18099  " toString: function () {"
18100  " if (i == 10) {"
18101  " throw 'Hey!';"
18102  " } else {"
18103  " i++;"
18104  " return s(o);"
18105  " }"
18106  " }"
18107  "};"
18108  "s(o);");
18109  CHECK(try_catch.HasCaught());
18110  v8::String::Utf8Value value(try_catch.Exception());
18111  CHECK_EQ(0, strcmp(*value, "Hey!"));
18112 }
18113 
18114 
18115 TEST(Regress528) {
18117  v8::Isolate* isolate = CcTest::isolate();
18118  v8::HandleScope scope(isolate);
18119  v8::Local<Context> other_context;
18120  int gc_count;
18121 
18122  // Create a context used to keep the code from aging in the compilation
18123  // cache.
18124  other_context = Context::New(isolate);
18125 
18126  // Context-dependent context data creates reference from the compilation
18127  // cache to the global object.
18128  const char* source_simple = "1";
18129  {
18130  v8::HandleScope scope(isolate);
18131  v8::Local<Context> context = Context::New(isolate);
18132 
18133  context->Enter();
18134  Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
18135  context->SetEmbedderData(0, obj);
18136  CompileRun(source_simple);
18137  context->Exit();
18138  }
18140  for (gc_count = 1; gc_count < 10; gc_count++) {
18141  other_context->Enter();
18142  CompileRun(source_simple);
18143  other_context->Exit();
18145  if (GetGlobalObjectsCount() == 1) break;
18146  }
18147  CHECK_GE(2, gc_count);
18148  CHECK_EQ(1, GetGlobalObjectsCount());
18149 
18150  // Eval in a function creates reference from the compilation cache to the
18151  // global object.
18152  const char* source_eval = "function f(){eval('1')}; f()";
18153  {
18154  v8::HandleScope scope(isolate);
18155  v8::Local<Context> context = Context::New(isolate);
18156 
18157  context->Enter();
18158  CompileRun(source_eval);
18159  context->Exit();
18160  }
18162  for (gc_count = 1; gc_count < 10; gc_count++) {
18163  other_context->Enter();
18164  CompileRun(source_eval);
18165  other_context->Exit();
18167  if (GetGlobalObjectsCount() == 1) break;
18168  }
18169  CHECK_GE(2, gc_count);
18170  CHECK_EQ(1, GetGlobalObjectsCount());
18171 
18172  // Looking up the line number for an exception creates reference from the
18173  // compilation cache to the global object.
18174  const char* source_exception = "function f(){throw 1;} f()";
18175  {
18176  v8::HandleScope scope(isolate);
18177  v8::Local<Context> context = Context::New(isolate);
18178 
18179  context->Enter();
18180  v8::TryCatch try_catch;
18181  CompileRun(source_exception);
18182  CHECK(try_catch.HasCaught());
18183  v8::Handle<v8::Message> message = try_catch.Message();
18184  CHECK(!message.IsEmpty());
18185  CHECK_EQ(1, message->GetLineNumber());
18186  context->Exit();
18187  }
18189  for (gc_count = 1; gc_count < 10; gc_count++) {
18190  other_context->Enter();
18191  CompileRun(source_exception);
18192  other_context->Exit();
18194  if (GetGlobalObjectsCount() == 1) break;
18195  }
18196  CHECK_GE(2, gc_count);
18197  CHECK_EQ(1, GetGlobalObjectsCount());
18198 
18200 }
18201 
18202 
18203 THREADED_TEST(ScriptOrigin) {
18204  LocalContext env;
18205  v8::HandleScope scope(env->GetIsolate());
18206  v8::ScriptOrigin origin =
18209  env->GetIsolate(), "function f() {}\n\nfunction g() {}");
18210  v8::Script::Compile(script, &origin)->Run();
18212  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18214  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18215 
18216  v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
18217  CHECK_EQ("test", *v8::String::Utf8Value(script_origin_f.ResourceName()));
18218  CHECK_EQ(0, script_origin_f.ResourceLineOffset()->Int32Value());
18219 
18220  v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
18221  CHECK_EQ("test", *v8::String::Utf8Value(script_origin_g.ResourceName()));
18222  CHECK_EQ(0, script_origin_g.ResourceLineOffset()->Int32Value());
18223 }
18224 
18225 
18226 THREADED_TEST(FunctionGetInferredName) {
18227  LocalContext env;
18228  v8::HandleScope scope(env->GetIsolate());
18229  v8::ScriptOrigin origin =
18232  env->GetIsolate(),
18233  "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
18234  v8::Script::Compile(script, &origin)->Run();
18236  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18237  CHECK_EQ("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName()));
18238 }
18239 
18240 
18241 THREADED_TEST(FunctionGetDisplayName) {
18242  LocalContext env;
18243  v8::HandleScope scope(env->GetIsolate());
18244  const char* code = "var error = false;"
18245  "function a() { this.x = 1; };"
18246  "a.displayName = 'display_a';"
18247  "var b = (function() {"
18248  " var f = function() { this.x = 2; };"
18249  " f.displayName = 'display_b';"
18250  " return f;"
18251  "})();"
18252  "var c = function() {};"
18253  "c.__defineGetter__('displayName', function() {"
18254  " error = true;"
18255  " throw new Error();"
18256  "});"
18257  "function d() {};"
18258  "d.__defineGetter__('displayName', function() {"
18259  " error = true;"
18260  " return 'wrong_display_name';"
18261  "});"
18262  "function e() {};"
18263  "e.displayName = 'wrong_display_name';"
18264  "e.__defineSetter__('displayName', function() {"
18265  " error = true;"
18266  " throw new Error();"
18267  "});"
18268  "function f() {};"
18269  "f.displayName = { 'foo': 6, toString: function() {"
18270  " error = true;"
18271  " return 'wrong_display_name';"
18272  "}};"
18273  "var g = function() {"
18274  " arguments.callee.displayName = 'set_in_runtime';"
18275  "}; g();"
18276  ;
18277  v8::ScriptOrigin origin =
18280  ->Run();
18281  v8::Local<v8::Value> error =
18282  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
18284  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
18286  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
18288  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
18290  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
18292  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
18294  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18296  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18297  CHECK_EQ(false, error->BooleanValue());
18298  CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
18299  CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
18300  CHECK(c->GetDisplayName()->IsUndefined());
18301  CHECK(d->GetDisplayName()->IsUndefined());
18302  CHECK(e->GetDisplayName()->IsUndefined());
18303  CHECK(f->GetDisplayName()->IsUndefined());
18304  CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
18305 }
18306 
18307 
18308 THREADED_TEST(ScriptLineNumber) {
18309  LocalContext env;
18310  v8::HandleScope scope(env->GetIsolate());
18311  v8::ScriptOrigin origin =
18314  env->GetIsolate(), "function f() {}\n\nfunction g() {}");
18315  v8::Script::Compile(script, &origin)->Run();
18317  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18319  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18320  CHECK_EQ(0, f->GetScriptLineNumber());
18321  CHECK_EQ(2, g->GetScriptLineNumber());
18322 }
18323 
18324 
18325 THREADED_TEST(ScriptColumnNumber) {
18326  LocalContext env;
18327  v8::Isolate* isolate = env->GetIsolate();
18328  v8::HandleScope scope(isolate);
18329  v8::ScriptOrigin origin =
18330  v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18331  v8::Integer::New(isolate, 3),
18332  v8::Integer::New(isolate, 2));
18334  isolate, "function foo() {}\n\n function bar() {}");
18335  v8::Script::Compile(script, &origin)->Run();
18337  env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
18339  env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
18340  CHECK_EQ(14, foo->GetScriptColumnNumber());
18341  CHECK_EQ(17, bar->GetScriptColumnNumber());
18342 }
18343 
18344 
18345 THREADED_TEST(FunctionIsBuiltin) {
18346  LocalContext env;
18347  v8::Isolate* isolate = env->GetIsolate();
18348  v8::HandleScope scope(isolate);
18350  f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
18351  CHECK(f->IsBuiltin());
18352  f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
18353  CHECK(f->IsBuiltin());
18354  f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
18355  CHECK(f->IsBuiltin());
18356  f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
18357  CHECK(f->IsBuiltin());
18358  f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
18359  CHECK(!f->IsBuiltin());
18360 }
18361 
18362 
18363 THREADED_TEST(FunctionGetScriptId) {
18364  LocalContext env;
18365  v8::Isolate* isolate = env->GetIsolate();
18366  v8::HandleScope scope(isolate);
18367  v8::ScriptOrigin origin =
18368  v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
18369  v8::Integer::New(isolate, 3),
18370  v8::Integer::New(isolate, 2));
18372  isolate, "function foo() {}\n\n function bar() {}");
18373  v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
18374  script->Run();
18376  env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
18378  env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
18379  CHECK_EQ(script->GetId(), foo->ScriptId());
18380  CHECK_EQ(script->GetId(), bar->ScriptId());
18381 }
18382 
18383 
18384 THREADED_TEST(FunctionGetBoundFunction) {
18385  LocalContext env;
18386  v8::HandleScope scope(env->GetIsolate());
18388  env->GetIsolate(), "test"));
18390  env->GetIsolate(),
18391  "var a = new Object();\n"
18392  "a.x = 1;\n"
18393  "function f () { return this.x };\n"
18394  "var g = f.bind(a);\n"
18395  "var b = g();");
18396  v8::Script::Compile(script, &origin)->Run();
18398  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
18400  env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
18401  CHECK(g->GetBoundFunction()->IsFunction());
18402  Local<v8::Function> original_function = Local<v8::Function>::Cast(
18403  g->GetBoundFunction());
18404  CHECK_EQ(f->GetName(), original_function->GetName());
18405  CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
18407  original_function->GetScriptColumnNumber());
18408 }
18409 
18410 
18411 static void GetterWhichReturns42(
18412  Local<String> name,
18414  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18415  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18416  info.GetReturnValue().Set(v8_num(42));
18417 }
18418 
18419 
18420 static void SetterWhichSetsYOnThisTo23(
18421  Local<String> name,
18422  Local<Value> value,
18423  const v8::PropertyCallbackInfo<void>& info) {
18424  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18425  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18426  info.This()->Set(v8_str("y"), v8_num(23));
18427 }
18428 
18429 
18430 void FooGetInterceptor(Local<String> name,
18432  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18433  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18434  if (!name->Equals(v8_str("foo"))) return;
18435  info.GetReturnValue().Set(v8_num(42));
18436 }
18437 
18438 
18439 void FooSetInterceptor(Local<String> name,
18440  Local<Value> value,
18442  CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
18443  CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
18444  if (!name->Equals(v8_str("foo"))) return;
18445  info.This()->Set(v8_str("y"), v8_num(23));
18446  info.GetReturnValue().Set(v8_num(23));
18447 }
18448 
18449 
18450 TEST(SetterOnConstructorPrototype) {
18451  v8::Isolate* isolate = CcTest::isolate();
18452  v8::HandleScope scope(isolate);
18453  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18454  templ->SetAccessor(v8_str("x"),
18455  GetterWhichReturns42,
18456  SetterWhichSetsYOnThisTo23);
18457  LocalContext context;
18458  context->Global()->Set(v8_str("P"), templ->NewInstance());
18459  CompileRun("function C1() {"
18460  " this.x = 23;"
18461  "};"
18462  "C1.prototype = P;"
18463  "function C2() {"
18464  " this.x = 23"
18465  "};"
18466  "C2.prototype = { };"
18467  "C2.prototype.__proto__ = P;");
18468 
18469  v8::Local<v8::Script> script;
18470  script = v8_compile("new C1();");
18471  for (int i = 0; i < 10; i++) {
18473  CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18474  CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18475  }
18476 
18477 script = v8_compile("new C2();");
18478  for (int i = 0; i < 10; i++) {
18480  CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
18481  CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
18482  }
18483 }
18484 
18485 
18486 static void NamedPropertyGetterWhichReturns42(
18487  Local<String> name,
18489  info.GetReturnValue().Set(v8_num(42));
18490 }
18491 
18492 
18493 static void NamedPropertySetterWhichSetsYOnThisTo23(
18494  Local<String> name,
18495  Local<Value> value,
18497  if (name->Equals(v8_str("x"))) {
18498  info.This()->Set(v8_str("y"), v8_num(23));
18499  }
18500 }
18501 
18502 
18503 THREADED_TEST(InterceptorOnConstructorPrototype) {
18504  v8::Isolate* isolate = CcTest::isolate();
18505  v8::HandleScope scope(isolate);
18506  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18507  templ->SetNamedPropertyHandler(NamedPropertyGetterWhichReturns42,
18508  NamedPropertySetterWhichSetsYOnThisTo23);
18509  LocalContext context;
18510  context->Global()->Set(v8_str("P"), templ->NewInstance());
18511  CompileRun("function C1() {"
18512  " this.x = 23;"
18513  "};"
18514  "C1.prototype = P;"
18515  "function C2() {"
18516  " this.x = 23"
18517  "};"
18518  "C2.prototype = { };"
18519  "C2.prototype.__proto__ = P;");
18520 
18521  v8::Local<v8::Script> script;
18522  script = v8_compile("new C1();");
18523  for (int i = 0; i < 10; i++) {
18525  CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18526  CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18527  }
18528 
18529  script = v8_compile("new C2();");
18530  for (int i = 0; i < 10; i++) {
18532  CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
18533  CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
18534  }
18535 }
18536 
18537 
18538 TEST(Regress618) {
18539  const char* source = "function C1() {"
18540  " this.x = 23;"
18541  "};"
18542  "C1.prototype = P;";
18543 
18544  LocalContext context;
18545  v8::Isolate* isolate = context->GetIsolate();
18546  v8::HandleScope scope(isolate);
18547  v8::Local<v8::Script> script;
18548 
18549  // Use a simple object as prototype.
18550  v8::Local<v8::Object> prototype = v8::Object::New(isolate);
18551  prototype->Set(v8_str("y"), v8_num(42));
18552  context->Global()->Set(v8_str("P"), prototype);
18553 
18554  // This compile will add the code to the compilation cache.
18555  CompileRun(source);
18556 
18557  script = v8_compile("new C1();");
18558  // Allow enough iterations for the inobject slack tracking logic
18559  // to finalize instance size and install the fast construct stub.
18560  for (int i = 0; i < 256; i++) {
18562  CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
18563  CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
18564  }
18565 
18566  // Use an API object with accessors as prototype.
18567  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18568  templ->SetAccessor(v8_str("x"),
18569  GetterWhichReturns42,
18570  SetterWhichSetsYOnThisTo23);
18571  context->Global()->Set(v8_str("P"), templ->NewInstance());
18572 
18573  // This compile will get the code from the compilation cache.
18574  CompileRun(source);
18575 
18576  script = v8_compile("new C1();");
18577  for (int i = 0; i < 10; i++) {
18579  CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
18580  CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
18581  }
18582 }
18583 
18591 
18595 }
18596 
18597 
18599  v8::GCType,
18602  CHECK_EQ(gc_callbacks_isolate, isolate);
18604 }
18605 
18606 
18610 }
18611 
18612 
18614  v8::GCType,
18617  CHECK_EQ(gc_callbacks_isolate, isolate);
18619 }
18620 
18621 
18625 }
18626 
18627 
18629  v8::GCType,
18632  CHECK_EQ(gc_callbacks_isolate, isolate);
18634 }
18635 
18636 
18640 }
18641 
18642 
18644  v8::GCType,
18647  CHECK_EQ(gc_callbacks_isolate, isolate);
18649 }
18650 
18651 
18653  v8::GCType,
18655  v8::HandleScope scope(isolate);
18656 
18658  CHECK_EQ(gc_callbacks_isolate, isolate);
18660 
18661  // Simulate full heap to see if we will reenter this callback
18662  SimulateFullSpace(CcTest::heap()->new_space());
18663 
18664  Local<Object> obj = Object::New(isolate);
18665  CHECK(!obj.IsEmpty());
18666 
18669 }
18670 
18671 
18673  v8::GCType,
18675  v8::HandleScope scope(isolate);
18676 
18678  CHECK_EQ(gc_callbacks_isolate, isolate);
18680 
18681  // Simulate full heap to see if we will reenter this callback
18682  SimulateFullSpace(CcTest::heap()->new_space());
18683 
18684  Local<Object> obj = Object::New(isolate);
18685  CHECK(!obj.IsEmpty());
18686 
18689 }
18690 
18691 
18692 TEST(GCCallbacksOld) {
18693  LocalContext context;
18694 
18697  CHECK_EQ(0, prologue_call_count);
18698  CHECK_EQ(0, epilogue_call_count);
18700  CHECK_EQ(1, prologue_call_count);
18701  CHECK_EQ(1, epilogue_call_count);
18705  CHECK_EQ(2, prologue_call_count);
18706  CHECK_EQ(2, epilogue_call_count);
18707  CHECK_EQ(1, prologue_call_count_second);
18708  CHECK_EQ(1, epilogue_call_count_second);
18712  CHECK_EQ(2, prologue_call_count);
18713  CHECK_EQ(2, epilogue_call_count);
18714  CHECK_EQ(2, prologue_call_count_second);
18715  CHECK_EQ(2, epilogue_call_count_second);
18719  CHECK_EQ(2, prologue_call_count);
18720  CHECK_EQ(2, epilogue_call_count);
18721  CHECK_EQ(2, prologue_call_count_second);
18722  CHECK_EQ(2, epilogue_call_count_second);
18723 }
18724 
18725 
18726 TEST(GCCallbacks) {
18727  LocalContext context;
18728  v8::Isolate* isolate = context->GetIsolate();
18729  gc_callbacks_isolate = isolate;
18732  CHECK_EQ(0, prologue_call_count);
18733  CHECK_EQ(0, epilogue_call_count);
18735  CHECK_EQ(1, prologue_call_count);
18736  CHECK_EQ(1, epilogue_call_count);
18740  CHECK_EQ(2, prologue_call_count);
18741  CHECK_EQ(2, epilogue_call_count);
18742  CHECK_EQ(1, prologue_call_count_second);
18743  CHECK_EQ(1, epilogue_call_count_second);
18747  CHECK_EQ(2, prologue_call_count);
18748  CHECK_EQ(2, epilogue_call_count);
18749  CHECK_EQ(2, prologue_call_count_second);
18750  CHECK_EQ(2, epilogue_call_count_second);
18754  CHECK_EQ(2, prologue_call_count);
18755  CHECK_EQ(2, epilogue_call_count);
18756  CHECK_EQ(2, prologue_call_count_second);
18757  CHECK_EQ(2, epilogue_call_count_second);
18758 
18759  CHECK_EQ(0, prologue_call_count_alloc);
18760  CHECK_EQ(0, epilogue_call_count_alloc);
18765  CHECK_EQ(1, prologue_call_count_alloc);
18766  CHECK_EQ(1, epilogue_call_count_alloc);
18769 }
18770 
18771 
18772 THREADED_TEST(AddToJSFunctionResultCache) {
18773  i::FLAG_stress_compaction = false;
18774  i::FLAG_allow_natives_syntax = true;
18776 
18777  LocalContext context;
18778 
18779  const char* code =
18780  "(function() {"
18781  " var key0 = 'a';"
18782  " var key1 = 'b';"
18783  " var r0 = %_GetFromCache(0, key0);"
18784  " var r1 = %_GetFromCache(0, key1);"
18785  " var r0_ = %_GetFromCache(0, key0);"
18786  " if (r0 !== r0_)"
18787  " return 'Different results for ' + key0 + ': ' + r0 + ' vs. ' + r0_;"
18788  " var r1_ = %_GetFromCache(0, key1);"
18789  " if (r1 !== r1_)"
18790  " return 'Different results for ' + key1 + ': ' + r1 + ' vs. ' + r1_;"
18791  " return 'PASSED';"
18792  "})()";
18794  ExpectString(code, "PASSED");
18795 }
18796 
18797 
18798 THREADED_TEST(FillJSFunctionResultCache) {
18799  i::FLAG_allow_natives_syntax = true;
18800  LocalContext context;
18801  v8::HandleScope scope(context->GetIsolate());
18802 
18803  const char* code =
18804  "(function() {"
18805  " var k = 'a';"
18806  " var r = %_GetFromCache(0, k);"
18807  " for (var i = 0; i < 16; i++) {"
18808  " %_GetFromCache(0, 'a' + i);"
18809  " };"
18810  " if (r === %_GetFromCache(0, k))"
18811  " return 'FAILED: k0CacheSize is too small';"
18812  " return 'PASSED';"
18813  "})()";
18815  ExpectString(code, "PASSED");
18816 }
18817 
18818 
18819 THREADED_TEST(RoundRobinGetFromCache) {
18820  i::FLAG_allow_natives_syntax = true;
18821  LocalContext context;
18822  v8::HandleScope scope(context->GetIsolate());
18823 
18824  const char* code =
18825  "(function() {"
18826  " var keys = [];"
18827  " for (var i = 0; i < 16; i++) keys.push(i);"
18828  " var values = [];"
18829  " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18830  " for (var i = 0; i < 16; i++) {"
18831  " var v = %_GetFromCache(0, keys[i]);"
18832  " if (v.toString() !== values[i].toString())"
18833  " return 'Wrong value for ' + "
18834  " keys[i] + ': ' + v + ' vs. ' + values[i];"
18835  " };"
18836  " return 'PASSED';"
18837  "})()";
18839  ExpectString(code, "PASSED");
18840 }
18841 
18842 
18843 THREADED_TEST(ReverseGetFromCache) {
18844  i::FLAG_allow_natives_syntax = true;
18845  LocalContext context;
18846  v8::HandleScope scope(context->GetIsolate());
18847 
18848  const char* code =
18849  "(function() {"
18850  " var keys = [];"
18851  " for (var i = 0; i < 16; i++) keys.push(i);"
18852  " var values = [];"
18853  " for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
18854  " for (var i = 15; i >= 16; i--) {"
18855  " var v = %_GetFromCache(0, keys[i]);"
18856  " if (v !== values[i])"
18857  " return 'Wrong value for ' + "
18858  " keys[i] + ': ' + v + ' vs. ' + values[i];"
18859  " };"
18860  " return 'PASSED';"
18861  "})()";
18863  ExpectString(code, "PASSED");
18864 }
18865 
18866 
18867 THREADED_TEST(TestEviction) {
18868  i::FLAG_allow_natives_syntax = true;
18869  LocalContext context;
18870  v8::HandleScope scope(context->GetIsolate());
18871 
18872  const char* code =
18873  "(function() {"
18874  " for (var i = 0; i < 2*16; i++) {"
18875  " %_GetFromCache(0, 'a' + i);"
18876  " };"
18877  " return 'PASSED';"
18878  "})()";
18880  ExpectString(code, "PASSED");
18881 }
18882 
18883 
18884 THREADED_TEST(TwoByteStringInAsciiCons) {
18885  // See Chromium issue 47824.
18886  LocalContext context;
18887  v8::HandleScope scope(context->GetIsolate());
18888 
18889  const char* init_code =
18890  "var str1 = 'abelspendabel';"
18891  "var str2 = str1 + str1 + str1;"
18892  "str2;";
18893  Local<Value> result = CompileRun(init_code);
18894 
18895  Local<Value> indexof = CompileRun("str2.indexOf('els')");
18896  Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
18897 
18898  CHECK(result->IsString());
18899  i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
18900  int length = string->length();
18901  CHECK(string->IsOneByteRepresentation());
18902 
18903  FlattenString(string);
18904  i::Handle<i::String> flat_string = FlattenGetString(string);
18905 
18906  CHECK(string->IsOneByteRepresentation());
18907  CHECK(flat_string->IsOneByteRepresentation());
18908 
18909  // Create external resource.
18910  uint16_t* uc16_buffer = new uint16_t[length + 1];
18911 
18912  i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
18913  uc16_buffer[length] = 0;
18914 
18915  TestResource resource(uc16_buffer);
18916 
18917  flat_string->MakeExternal(&resource);
18918 
18919  CHECK(flat_string->IsTwoByteRepresentation());
18920 
18921  // If the cons string has been short-circuited, skip the following checks.
18922  if (!string.is_identical_to(flat_string)) {
18923  // At this point, we should have a Cons string which is flat and ASCII,
18924  // with a first half that is a two-byte string (although it only contains
18925  // ASCII characters). This is a valid sequence of steps, and it can happen
18926  // in real pages.
18927  CHECK(string->IsOneByteRepresentation());
18928  i::ConsString* cons = i::ConsString::cast(*string);
18929  CHECK_EQ(0, cons->second()->length());
18930  CHECK(cons->first()->IsTwoByteRepresentation());
18931  }
18932 
18933  // Check that some string operations work.
18934 
18935  // Atom RegExp.
18936  Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
18937  CHECK_EQ(6, reresult->Int32Value());
18938 
18939  // Nonatom RegExp.
18940  reresult = CompileRun("str2.match(/abe./g).length;");
18941  CHECK_EQ(6, reresult->Int32Value());
18942 
18943  reresult = CompileRun("str2.search(/bel/g);");
18944  CHECK_EQ(1, reresult->Int32Value());
18945 
18946  reresult = CompileRun("str2.search(/be./g);");
18947  CHECK_EQ(1, reresult->Int32Value());
18948 
18949  ExpectTrue("/bel/g.test(str2);");
18950 
18951  ExpectTrue("/be./g.test(str2);");
18952 
18953  reresult = CompileRun("/bel/g.exec(str2);");
18954  CHECK(!reresult->IsNull());
18955 
18956  reresult = CompileRun("/be./g.exec(str2);");
18957  CHECK(!reresult->IsNull());
18958 
18959  ExpectString("str2.substring(2, 10);", "elspenda");
18960 
18961  ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
18962 
18963  ExpectString("str2.charAt(2);", "e");
18964 
18965  ExpectObject("str2.indexOf('els');", indexof);
18966 
18967  ExpectObject("str2.lastIndexOf('dab');", lastindexof);
18968 
18969  reresult = CompileRun("str2.charCodeAt(2);");
18970  CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
18971 }
18972 
18973 
18974 TEST(ContainsOnlyOneByte) {
18976  v8::Isolate* isolate = CcTest::isolate();
18977  v8::HandleScope scope(isolate);
18978  // Make a buffer long enough that it won't automatically be converted.
18979  const int length = 512;
18980  // Ensure word aligned assignment.
18981  const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
18983  aligned_contents(new uintptr_t[aligned_length]);
18984  uint16_t* string_contents =
18985  reinterpret_cast<uint16_t*>(aligned_contents.get());
18986  // Set to contain only one byte.
18987  for (int i = 0; i < length-1; i++) {
18988  string_contents[i] = 0x41;
18989  }
18990  string_contents[length-1] = 0;
18991  // Simple case.
18992  Handle<String> string =
18993  String::NewExternal(isolate,
18994  new TestResource(string_contents, NULL, false));
18995  CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
18996  // Counter example.
18997  string = String::NewFromTwoByte(isolate, string_contents);
18998  CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
18999  // Test left right and balanced cons strings.
19000  Handle<String> base = String::NewFromUtf8(isolate, "a");
19001  Handle<String> left = base;
19002  Handle<String> right = base;
19003  for (int i = 0; i < 1000; i++) {
19004  left = String::Concat(base, left);
19005  right = String::Concat(right, base);
19006  }
19007  Handle<String> balanced = String::Concat(left, base);
19008  balanced = String::Concat(balanced, right);
19009  Handle<String> cons_strings[] = {left, balanced, right};
19010  Handle<String> two_byte =
19011  String::NewExternal(isolate,
19012  new TestResource(string_contents, NULL, false));
19013  USE(two_byte); USE(cons_strings);
19014  for (size_t i = 0; i < ARRAY_SIZE(cons_strings); i++) {
19015  // Base assumptions.
19016  string = cons_strings[i];
19017  CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
19018  // Test left and right concatentation.
19019  string = String::Concat(two_byte, cons_strings[i]);
19020  CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19021  string = String::Concat(cons_strings[i], two_byte);
19022  CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
19023  }
19024  // Set bits in different positions
19025  // for strings of different lengths and alignments.
19026  for (int alignment = 0; alignment < 7; alignment++) {
19027  for (int size = 2; alignment + size < length; size *= 2) {
19028  int zero_offset = size + alignment;
19029  string_contents[zero_offset] = 0;
19030  for (int i = 0; i < size; i++) {
19031  int shift = 8 + (i % 7);
19032  string_contents[alignment + i] = 1 << shift;
19033  string = String::NewExternal(
19034  isolate,
19035  new TestResource(string_contents + alignment, NULL, false));
19036  CHECK_EQ(size, string->Length());
19037  CHECK(!string->ContainsOnlyOneByte());
19038  string_contents[alignment + i] = 0x41;
19039  }
19040  string_contents[zero_offset] = 0x41;
19041  }
19042  }
19043 }
19044 
19045 
19046 // Failed access check callback that performs a GC on each invocation.
19047 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
19048  v8::AccessType type,
19049  Local<v8::Value> data) {
19051 }
19052 
19053 
19054 TEST(GCInFailedAccessCheckCallback) {
19055  // Install a failed access check callback that performs a GC on each
19056  // invocation. Then force the callback to be called from va
19057 
19060 
19061  v8::Isolate* isolate = CcTest::isolate();
19062  v8::HandleScope scope(isolate);
19063 
19064  // Create an ObjectTemplate for global objects and install access
19065  // check callbacks that will block access.
19066  v8::Handle<v8::ObjectTemplate> global_template =
19067  v8::ObjectTemplate::New(isolate);
19068  global_template->SetAccessCheckCallbacks(NamedGetAccessBlocker,
19069  IndexedGetAccessBlocker,
19071  false);
19072 
19073  // Create a context and set an x property on it's global object.
19074  LocalContext context0(NULL, global_template);
19075  context0->Global()->Set(v8_str("x"), v8_num(42));
19076  v8::Handle<v8::Object> global0 = context0->Global();
19077 
19078  // Create a context with a different security token so that the
19079  // failed access check callback will be called on each access.
19080  LocalContext context1(NULL, global_template);
19081  context1->Global()->Set(v8_str("other"), global0);
19082 
19083  // Get property with failed access check.
19084  ExpectUndefined("other.x");
19085 
19086  // Get element with failed access check.
19087  ExpectUndefined("other[0]");
19088 
19089  // Set property with failed access check.
19090  v8::Handle<v8::Value> result = CompileRun("other.x = new Object()");
19091  CHECK(result->IsObject());
19092 
19093  // Set element with failed access check.
19094  result = CompileRun("other[0] = new Object()");
19095  CHECK(result->IsObject());
19096 
19097  // Get property attribute with failed access check.
19098  ExpectFalse("\'x\' in other");
19099 
19100  // Get property attribute for element with failed access check.
19101  ExpectFalse("0 in other");
19102 
19103  // Delete property.
19104  ExpectFalse("delete other.x");
19105 
19106  // Delete element.
19107  CHECK_EQ(false, global0->Delete(0));
19108 
19109  // DefineAccessor.
19110  CHECK_EQ(false,
19111  global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
19112 
19113  // Define JavaScript accessor.
19114  ExpectUndefined("Object.prototype.__defineGetter__.call("
19115  " other, \'x\', function() { return 42; })");
19116 
19117  // LookupAccessor.
19118  ExpectUndefined("Object.prototype.__lookupGetter__.call("
19119  " other, \'x\')");
19120 
19121  // HasLocalElement.
19122  ExpectFalse("Object.prototype.hasOwnProperty.call(other, \'0\')");
19123 
19124  CHECK_EQ(false, global0->HasRealIndexedProperty(0));
19125  CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
19126  CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
19127 
19128  // Reset the failed access check callback so it does not influence
19129  // the other tests.
19131 }
19132 
19133 
19134 TEST(IsolateNewDispose) {
19135  v8::Isolate* current_isolate = CcTest::isolate();
19136  v8::Isolate* isolate = v8::Isolate::New();
19137  CHECK(isolate != NULL);
19138  CHECK(!reinterpret_cast<i::Isolate*>(isolate)->IsDefaultIsolate());
19139  CHECK(current_isolate != isolate);
19140  CHECK(current_isolate == CcTest::isolate());
19141 
19143  last_location = last_message = NULL;
19144  isolate->Dispose();
19145  CHECK_EQ(last_location, NULL);
19146  CHECK_EQ(last_message, NULL);
19147 }
19148 
19149 
19150 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
19151  v8::Isolate* isolate = v8::Isolate::New();
19152  {
19153  v8::Isolate::Scope i_scope(isolate);
19154  v8::HandleScope scope(isolate);
19155  LocalContext context(isolate);
19156  // Run something in this isolate.
19157  ExpectTrue("true");
19159  last_location = last_message = NULL;
19160  // Still entered, should fail.
19161  isolate->Dispose();
19162  CHECK_NE(last_location, NULL);
19163  CHECK_NE(last_message, NULL);
19164  }
19165  isolate->Dispose();
19166 }
19167 
19168 
19169 TEST(RunTwoIsolatesOnSingleThread) {
19170  // Run isolate 1.
19171  v8::Isolate* isolate1 = v8::Isolate::New();
19172  isolate1->Enter();
19173  v8::Persistent<v8::Context> context1;
19174  {
19175  v8::HandleScope scope(isolate1);
19176  context1.Reset(isolate1, Context::New(isolate1));
19177  }
19178 
19179  {
19180  v8::HandleScope scope(isolate1);
19181  v8::Local<v8::Context> context =
19182  v8::Local<v8::Context>::New(isolate1, context1);
19183  v8::Context::Scope context_scope(context);
19184  // Run something in new isolate.
19185  CompileRun("var foo = 'isolate 1';");
19186  ExpectString("function f() { return foo; }; f()", "isolate 1");
19187  }
19188 
19189  // Run isolate 2.
19190  v8::Isolate* isolate2 = v8::Isolate::New();
19191  v8::Persistent<v8::Context> context2;
19192 
19193  {
19194  v8::Isolate::Scope iscope(isolate2);
19195  v8::HandleScope scope(isolate2);
19196  context2.Reset(isolate2, Context::New(isolate2));
19197  v8::Local<v8::Context> context =
19198  v8::Local<v8::Context>::New(isolate2, context2);
19199  v8::Context::Scope context_scope(context);
19200 
19201  // Run something in new isolate.
19202  CompileRun("var foo = 'isolate 2';");
19203  ExpectString("function f() { return foo; }; f()", "isolate 2");
19204  }
19205 
19206  {
19207  v8::HandleScope scope(isolate1);
19208  v8::Local<v8::Context> context =
19209  v8::Local<v8::Context>::New(isolate1, context1);
19210  v8::Context::Scope context_scope(context);
19211  // Now again in isolate 1
19212  ExpectString("function f() { return foo; }; f()", "isolate 1");
19213  }
19214 
19215  isolate1->Exit();
19216 
19217  // Run some stuff in default isolate.
19218  v8::Persistent<v8::Context> context_default;
19219  {
19220  v8::Isolate* isolate = CcTest::isolate();
19221  v8::Isolate::Scope iscope(isolate);
19222  v8::HandleScope scope(isolate);
19223  context_default.Reset(isolate, Context::New(isolate));
19224  }
19225 
19226  {
19228  v8::Local<v8::Context> context =
19229  v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19230  v8::Context::Scope context_scope(context);
19231  // Variables in other isolates should be not available, verify there
19232  // is an exception.
19233  ExpectTrue("function f() {"
19234  " try {"
19235  " foo;"
19236  " return false;"
19237  " } catch(e) {"
19238  " return true;"
19239  " }"
19240  "};"
19241  "var isDefaultIsolate = true;"
19242  "f()");
19243  }
19244 
19245  isolate1->Enter();
19246 
19247  {
19248  v8::Isolate::Scope iscope(isolate2);
19249  v8::HandleScope scope(isolate2);
19250  v8::Local<v8::Context> context =
19251  v8::Local<v8::Context>::New(isolate2, context2);
19252  v8::Context::Scope context_scope(context);
19253  ExpectString("function f() { return foo; }; f()", "isolate 2");
19254  }
19255 
19256  {
19258  v8::Local<v8::Context> context =
19260  v8::Context::Scope context_scope(context);
19261  ExpectString("function f() { return foo; }; f()", "isolate 1");
19262  }
19263 
19264  {
19265  v8::Isolate::Scope iscope(isolate2);
19266  context2.Reset();
19267  }
19268 
19269  context1.Reset();
19270  isolate1->Exit();
19271 
19273  last_location = last_message = NULL;
19274 
19275  isolate1->Dispose();
19276  CHECK_EQ(last_location, NULL);
19277  CHECK_EQ(last_message, NULL);
19278 
19279  isolate2->Dispose();
19280  CHECK_EQ(last_location, NULL);
19281  CHECK_EQ(last_message, NULL);
19282 
19283  // Check that default isolate still runs.
19284  {
19286  v8::Local<v8::Context> context =
19287  v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
19288  v8::Context::Scope context_scope(context);
19289  ExpectTrue("function f() { return isDefaultIsolate; }; f()");
19290  }
19291 }
19292 
19293 
19294 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
19295  v8::Isolate::Scope isolate_scope(isolate);
19296  v8::HandleScope scope(isolate);
19297  LocalContext context(isolate);
19299  i::OS::SNPrintF(code, "function fib(n) {"
19300  " if (n <= 2) return 1;"
19301  " return fib(n-1) + fib(n-2);"
19302  "}"
19303  "fib(%d)", limit);
19304  Local<Value> value = CompileRun(code.start());
19305  CHECK(value->IsNumber());
19306  return static_cast<int>(value->NumberValue());
19307 }
19308 
19310  public:
19311  IsolateThread(v8::Isolate* isolate, int fib_limit)
19312  : Thread("IsolateThread"),
19313  isolate_(isolate),
19314  fib_limit_(fib_limit),
19315  result_(0) { }
19316 
19317  void Run() {
19318  result_ = CalcFibonacci(isolate_, fib_limit_);
19319  }
19320 
19321  int result() { return result_; }
19322 
19323  private:
19324  v8::Isolate* isolate_;
19325  int fib_limit_;
19326  int result_;
19327 };
19328 
19329 
19330 TEST(MultipleIsolatesOnIndividualThreads) {
19331  v8::Isolate* isolate1 = v8::Isolate::New();
19332  v8::Isolate* isolate2 = v8::Isolate::New();
19333 
19334  IsolateThread thread1(isolate1, 21);
19335  IsolateThread thread2(isolate2, 12);
19336 
19337  // Compute some fibonacci numbers on 3 threads in 3 isolates.
19338  thread1.Start();
19339  thread2.Start();
19340 
19341  int result1 = CalcFibonacci(CcTest::isolate(), 21);
19342  int result2 = CalcFibonacci(CcTest::isolate(), 12);
19343 
19344  thread1.Join();
19345  thread2.Join();
19346 
19347  // Compare results. The actual fibonacci numbers for 12 and 21 are taken
19348  // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
19349  CHECK_EQ(result1, 10946);
19350  CHECK_EQ(result2, 144);
19351  CHECK_EQ(result1, thread1.result());
19352  CHECK_EQ(result2, thread2.result());
19353 
19354  isolate1->Dispose();
19355  isolate2->Dispose();
19356 }
19357 
19358 
19359 TEST(IsolateDifferentContexts) {
19360  v8::Isolate* isolate = v8::Isolate::New();
19361  Local<v8::Context> context;
19362  {
19363  v8::Isolate::Scope isolate_scope(isolate);
19364  v8::HandleScope handle_scope(isolate);
19365  context = v8::Context::New(isolate);
19366  v8::Context::Scope context_scope(context);
19367  Local<Value> v = CompileRun("2");
19368  CHECK(v->IsNumber());
19369  CHECK_EQ(2, static_cast<int>(v->NumberValue()));
19370  }
19371  {
19372  v8::Isolate::Scope isolate_scope(isolate);
19373  v8::HandleScope handle_scope(isolate);
19374  context = v8::Context::New(isolate);
19375  v8::Context::Scope context_scope(context);
19376  Local<Value> v = CompileRun("22");
19377  CHECK(v->IsNumber());
19378  CHECK_EQ(22, static_cast<int>(v->NumberValue()));
19379  }
19380  isolate->Dispose();
19381 }
19382 
19384  public:
19385  enum TestCase {
19391  };
19392 
19394  : Thread("InitDefaultIsolateThread"),
19395  testCase_(testCase),
19396  result_(false) { }
19397 
19398  void Run() {
19399  v8::Isolate* isolate = v8::Isolate::New();
19400  isolate->Enter();
19401  switch (testCase_) {
19402  case SetResourceConstraints: {
19403  static const int K = 1024;
19404  v8::ResourceConstraints constraints;
19405  constraints.set_max_young_space_size(256 * K);
19406  constraints.set_max_old_space_size(4 * K * K);
19408  break;
19409  }
19410 
19411  case SetFatalHandler:
19413  break;
19414 
19415  case SetCounterFunction:
19417  break;
19418 
19421  break;
19422 
19425  break;
19426  }
19427  isolate->Exit();
19428  isolate->Dispose();
19429  result_ = true;
19430  }
19431 
19432  bool result() { return result_; }
19433 
19434  private:
19435  TestCase testCase_;
19436  bool result_;
19437 };
19438 
19439 
19440 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
19441  InitDefaultIsolateThread thread(testCase);
19442  thread.Start();
19443  thread.Join();
19444  CHECK_EQ(thread.result(), true);
19445 }
19446 
19447 
19448 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
19450 }
19451 
19452 
19453 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
19454  InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
19455 }
19456 
19457 
19458 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
19459  InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
19460 }
19461 
19462 
19463 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
19465 }
19466 
19467 
19468 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
19470 }
19471 
19472 
19473 TEST(StringCheckMultipleContexts) {
19474  const char* code =
19475  "(function() { return \"a\".charAt(0); })()";
19476 
19477  {
19478  // Run the code twice in the first context to initialize the call IC.
19479  LocalContext context1;
19480  v8::HandleScope scope(context1->GetIsolate());
19481  ExpectString(code, "a");
19482  ExpectString(code, "a");
19483  }
19484 
19485  {
19486  // Change the String.prototype in the second context and check
19487  // that the right function gets called.
19488  LocalContext context2;
19489  v8::HandleScope scope(context2->GetIsolate());
19490  CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
19491  ExpectString(code, "not a");
19492  }
19493 }
19494 
19495 
19496 TEST(NumberCheckMultipleContexts) {
19497  const char* code =
19498  "(function() { return (42).toString(); })()";
19499 
19500  {
19501  // Run the code twice in the first context to initialize the call IC.
19502  LocalContext context1;
19503  v8::HandleScope scope(context1->GetIsolate());
19504  ExpectString(code, "42");
19505  ExpectString(code, "42");
19506  }
19507 
19508  {
19509  // Change the Number.prototype in the second context and check
19510  // that the right function gets called.
19511  LocalContext context2;
19512  v8::HandleScope scope(context2->GetIsolate());
19513  CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
19514  ExpectString(code, "not 42");
19515  }
19516 }
19517 
19518 
19519 TEST(BooleanCheckMultipleContexts) {
19520  const char* code =
19521  "(function() { return true.toString(); })()";
19522 
19523  {
19524  // Run the code twice in the first context to initialize the call IC.
19525  LocalContext context1;
19526  v8::HandleScope scope(context1->GetIsolate());
19527  ExpectString(code, "true");
19528  ExpectString(code, "true");
19529  }
19530 
19531  {
19532  // Change the Boolean.prototype in the second context and check
19533  // that the right function gets called.
19534  LocalContext context2;
19535  v8::HandleScope scope(context2->GetIsolate());
19536  CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
19537  ExpectString(code, "");
19538  }
19539 }
19540 
19541 
19542 TEST(DontDeleteCellLoadIC) {
19543  const char* function_code =
19544  "function readCell() { while (true) { return cell; } }";
19545 
19546  {
19547  // Run the code twice in the first context to initialize the load
19548  // IC for a don't delete cell.
19549  LocalContext context1;
19550  v8::HandleScope scope(context1->GetIsolate());
19551  CompileRun("var cell = \"first\";");
19552  ExpectBoolean("delete cell", false);
19553  CompileRun(function_code);
19554  ExpectString("readCell()", "first");
19555  ExpectString("readCell()", "first");
19556  }
19557 
19558  {
19559  // Use a deletable cell in the second context.
19560  LocalContext context2;
19561  v8::HandleScope scope(context2->GetIsolate());
19562  CompileRun("cell = \"second\";");
19563  CompileRun(function_code);
19564  ExpectString("readCell()", "second");
19565  ExpectBoolean("delete cell", true);
19566  ExpectString("(function() {"
19567  " try {"
19568  " return readCell();"
19569  " } catch(e) {"
19570  " return e.toString();"
19571  " }"
19572  "})()",
19573  "ReferenceError: cell is not defined");
19574  CompileRun("cell = \"new_second\";");
19576  ExpectString("readCell()", "new_second");
19577  ExpectString("readCell()", "new_second");
19578  }
19579 }
19580 
19581 
19582 TEST(DontDeleteCellLoadICForceDelete) {
19583  const char* function_code =
19584  "function readCell() { while (true) { return cell; } }";
19585 
19586  // Run the code twice to initialize the load IC for a don't delete
19587  // cell.
19588  LocalContext context;
19589  v8::HandleScope scope(context->GetIsolate());
19590  CompileRun("var cell = \"value\";");
19591  ExpectBoolean("delete cell", false);
19592  CompileRun(function_code);
19593  ExpectString("readCell()", "value");
19594  ExpectString("readCell()", "value");
19595 
19596  // Delete the cell using the API and check the inlined code works
19597  // correctly.
19598  CHECK(context->Global()->ForceDelete(v8_str("cell")));
19599  ExpectString("(function() {"
19600  " try {"
19601  " return readCell();"
19602  " } catch(e) {"
19603  " return e.toString();"
19604  " }"
19605  "})()",
19606  "ReferenceError: cell is not defined");
19607 }
19608 
19609 
19610 TEST(DontDeleteCellLoadICAPI) {
19611  const char* function_code =
19612  "function readCell() { while (true) { return cell; } }";
19613 
19614  // Run the code twice to initialize the load IC for a don't delete
19615  // cell created using the API.
19616  LocalContext context;
19617  v8::HandleScope scope(context->GetIsolate());
19618  context->Global()->Set(v8_str("cell"), v8_str("value"), v8::DontDelete);
19619  ExpectBoolean("delete cell", false);
19620  CompileRun(function_code);
19621  ExpectString("readCell()", "value");
19622  ExpectString("readCell()", "value");
19623 
19624  // Delete the cell using the API and check the inlined code works
19625  // correctly.
19626  CHECK(context->Global()->ForceDelete(v8_str("cell")));
19627  ExpectString("(function() {"
19628  " try {"
19629  " return readCell();"
19630  " } catch(e) {"
19631  " return e.toString();"
19632  " }"
19633  "})()",
19634  "ReferenceError: cell is not defined");
19635 }
19636 
19637 
19639  public:
19641  : counter_(0), object_(object) { }
19642 
19643  virtual void VisitPersistentHandle(Persistent<Value>* value,
19644  uint16_t class_id) {
19645  if (class_id != 42) return;
19646  CHECK_EQ(42, value->WrapperClassId());
19647  v8::Isolate* isolate = CcTest::isolate();
19648  v8::HandleScope handle_scope(isolate);
19650  v8::Handle<v8::Value> object =
19652  CHECK(handle->IsObject());
19653  CHECK_EQ(Handle<Object>::Cast(handle), object);
19654  ++counter_;
19655  }
19656 
19659 };
19660 
19661 
19662 TEST(PersistentHandleVisitor) {
19663  LocalContext context;
19664  v8::Isolate* isolate = context->GetIsolate();
19665  v8::HandleScope scope(isolate);
19666  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19667  CHECK_EQ(0, object.WrapperClassId());
19668  object.SetWrapperClassId(42);
19669  CHECK_EQ(42, object.WrapperClassId());
19670 
19671  Visitor42 visitor(&object);
19673  CHECK_EQ(1, visitor.counter_);
19674 
19675  object.Reset();
19676 }
19677 
19678 
19679 TEST(WrapperClassId) {
19680  LocalContext context;
19681  v8::Isolate* isolate = context->GetIsolate();
19682  v8::HandleScope scope(isolate);
19683  v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
19684  CHECK_EQ(0, object.WrapperClassId());
19685  object.SetWrapperClassId(65535);
19686  CHECK_EQ(65535, object.WrapperClassId());
19687  object.Reset();
19688 }
19689 
19690 
19691 TEST(PersistentHandleInNewSpaceVisitor) {
19692  LocalContext context;
19693  v8::Isolate* isolate = context->GetIsolate();
19694  v8::HandleScope scope(isolate);
19695  v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
19696  CHECK_EQ(0, object1.WrapperClassId());
19697  object1.SetWrapperClassId(42);
19698  CHECK_EQ(42, object1.WrapperClassId());
19699 
19701 
19702  v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
19703  CHECK_EQ(0, object2.WrapperClassId());
19704  object2.SetWrapperClassId(42);
19705  CHECK_EQ(42, object2.WrapperClassId());
19706 
19707  Visitor42 visitor(&object2);
19708  v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
19709  CHECK_EQ(1, visitor.counter_);
19710 
19711  object1.Reset();
19712  object2.Reset();
19713 }
19714 
19715 
19716 TEST(RegExp) {
19717  LocalContext context;
19718  v8::HandleScope scope(context->GetIsolate());
19719 
19721  CHECK(re->IsRegExp());
19722  CHECK(re->GetSource()->Equals(v8_str("foo")));
19723  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
19724 
19725  re = v8::RegExp::New(v8_str("bar"),
19726  static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19728  CHECK(re->IsRegExp());
19729  CHECK(re->GetSource()->Equals(v8_str("bar")));
19731  static_cast<int>(re->GetFlags()));
19732 
19733  re = v8::RegExp::New(v8_str("baz"),
19734  static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19736  CHECK(re->IsRegExp());
19737  CHECK(re->GetSource()->Equals(v8_str("baz")));
19739  static_cast<int>(re->GetFlags()));
19740 
19741  re = CompileRun("/quux/").As<v8::RegExp>();
19742  CHECK(re->IsRegExp());
19743  CHECK(re->GetSource()->Equals(v8_str("quux")));
19744  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
19745 
19746  re = CompileRun("/quux/gm").As<v8::RegExp>();
19747  CHECK(re->IsRegExp());
19748  CHECK(re->GetSource()->Equals(v8_str("quux")));
19750  static_cast<int>(re->GetFlags()));
19751 
19752  // Override the RegExp constructor and check the API constructor
19753  // still works.
19754  CompileRun("RegExp = function() {}");
19755 
19756  re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
19757  CHECK(re->IsRegExp());
19758  CHECK(re->GetSource()->Equals(v8_str("foobar")));
19759  CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
19760 
19761  re = v8::RegExp::New(v8_str("foobarbaz"),
19762  static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
19764  CHECK(re->IsRegExp());
19765  CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
19767  static_cast<int>(re->GetFlags()));
19768 
19769  context->Global()->Set(v8_str("re"), re);
19770  ExpectTrue("re.test('FoobarbaZ')");
19771 
19772  // RegExps are objects on which you can set properties.
19773  re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
19774  v8::Handle<v8::Value> value(CompileRun("re.property"));
19775  CHECK_EQ(32, value->Int32Value());
19776 
19777  v8::TryCatch try_catch;
19778  re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
19779  CHECK(re.IsEmpty());
19780  CHECK(try_catch.HasCaught());
19781  context->Global()->Set(v8_str("ex"), try_catch.Exception());
19782  ExpectTrue("ex instanceof SyntaxError");
19783 }
19784 
19785 
19786 THREADED_TEST(Equals) {
19787  LocalContext localContext;
19788  v8::HandleScope handleScope(localContext->GetIsolate());
19789 
19790  v8::Handle<v8::Object> globalProxy = localContext->Global();
19791  v8::Handle<Value> global = globalProxy->GetPrototype();
19792 
19793  CHECK(global->StrictEquals(global));
19794  CHECK(!global->StrictEquals(globalProxy));
19795  CHECK(!globalProxy->StrictEquals(global));
19796  CHECK(globalProxy->StrictEquals(globalProxy));
19797 
19798  CHECK(global->Equals(global));
19799  CHECK(!global->Equals(globalProxy));
19800  CHECK(!globalProxy->Equals(global));
19801  CHECK(globalProxy->Equals(globalProxy));
19802 }
19803 
19804 
19805 static void Getter(v8::Local<v8::String> property,
19806  const v8::PropertyCallbackInfo<v8::Value>& info ) {
19807  info.GetReturnValue().Set(v8_str("42!"));
19808 }
19809 
19810 
19811 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
19813  result->Set(0, v8_str("universalAnswer"));
19814  info.GetReturnValue().Set(result);
19815 }
19816 
19817 
19818 TEST(NamedEnumeratorAndForIn) {
19819  LocalContext context;
19820  v8::Isolate* isolate = context->GetIsolate();
19821  v8::HandleScope handle_scope(isolate);
19822  v8::Context::Scope context_scope(context.local());
19823 
19825  tmpl->SetNamedPropertyHandler(Getter, NULL, NULL, NULL, Enumerator);
19826  context->Global()->Set(v8_str("o"), tmpl->NewInstance());
19828  "var result = []; for (var k in o) result.push(k); result"));
19829  CHECK_EQ(1, result->Length());
19830  CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
19831 }
19832 
19833 
19834 TEST(DefinePropertyPostDetach) {
19835  LocalContext context;
19836  v8::HandleScope scope(context->GetIsolate());
19837  v8::Handle<v8::Object> proxy = context->Global();
19838  v8::Handle<v8::Function> define_property =
19839  CompileRun("(function() {"
19840  " Object.defineProperty("
19841  " this,"
19842  " 1,"
19843  " { configurable: true, enumerable: true, value: 3 });"
19844  "})").As<Function>();
19845  context->DetachGlobal();
19846  define_property->Call(proxy, 0, NULL);
19847 }
19848 
19849 
19850 static void InstallContextId(v8::Handle<Context> context, int id) {
19851  Context::Scope scope(context);
19852  CompileRun("Object.prototype").As<Object>()->
19853  Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
19854 }
19855 
19856 
19857 static void CheckContextId(v8::Handle<Object> object, int expected) {
19858  CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
19859 }
19860 
19861 
19862 THREADED_TEST(CreationContext) {
19863  v8::Isolate* isolate = CcTest::isolate();
19864  HandleScope handle_scope(isolate);
19865  Handle<Context> context1 = Context::New(isolate);
19866  InstallContextId(context1, 1);
19867  Handle<Context> context2 = Context::New(isolate);
19868  InstallContextId(context2, 2);
19869  Handle<Context> context3 = Context::New(isolate);
19870  InstallContextId(context3, 3);
19871 
19872  Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
19873 
19874  Local<Object> object1;
19875  Local<Function> func1;
19876  {
19877  Context::Scope scope(context1);
19878  object1 = Object::New(isolate);
19879  func1 = tmpl->GetFunction();
19880  }
19881 
19882  Local<Object> object2;
19883  Local<Function> func2;
19884  {
19885  Context::Scope scope(context2);
19886  object2 = Object::New(isolate);
19887  func2 = tmpl->GetFunction();
19888  }
19889 
19890  Local<Object> instance1;
19891  Local<Object> instance2;
19892 
19893  {
19894  Context::Scope scope(context3);
19895  instance1 = func1->NewInstance();
19896  instance2 = func2->NewInstance();
19897  }
19898 
19899  CHECK(object1->CreationContext() == context1);
19900  CheckContextId(object1, 1);
19901  CHECK(func1->CreationContext() == context1);
19902  CheckContextId(func1, 1);
19903  CHECK(instance1->CreationContext() == context1);
19904  CheckContextId(instance1, 1);
19905  CHECK(object2->CreationContext() == context2);
19906  CheckContextId(object2, 2);
19907  CHECK(func2->CreationContext() == context2);
19908  CheckContextId(func2, 2);
19909  CHECK(instance2->CreationContext() == context2);
19910  CheckContextId(instance2, 2);
19911 
19912  {
19913  Context::Scope scope(context1);
19914  CHECK(object1->CreationContext() == context1);
19915  CheckContextId(object1, 1);
19916  CHECK(func1->CreationContext() == context1);
19917  CheckContextId(func1, 1);
19918  CHECK(instance1->CreationContext() == context1);
19919  CheckContextId(instance1, 1);
19920  CHECK(object2->CreationContext() == context2);
19921  CheckContextId(object2, 2);
19922  CHECK(func2->CreationContext() == context2);
19923  CheckContextId(func2, 2);
19924  CHECK(instance2->CreationContext() == context2);
19925  CheckContextId(instance2, 2);
19926  }
19927 
19928  {
19929  Context::Scope scope(context2);
19930  CHECK(object1->CreationContext() == context1);
19931  CheckContextId(object1, 1);
19932  CHECK(func1->CreationContext() == context1);
19933  CheckContextId(func1, 1);
19934  CHECK(instance1->CreationContext() == context1);
19935  CheckContextId(instance1, 1);
19936  CHECK(object2->CreationContext() == context2);
19937  CheckContextId(object2, 2);
19938  CHECK(func2->CreationContext() == context2);
19939  CheckContextId(func2, 2);
19940  CHECK(instance2->CreationContext() == context2);
19941  CheckContextId(instance2, 2);
19942  }
19943 }
19944 
19945 
19946 THREADED_TEST(CreationContextOfJsFunction) {
19947  HandleScope handle_scope(CcTest::isolate());
19948  Handle<Context> context = Context::New(CcTest::isolate());
19949  InstallContextId(context, 1);
19950 
19951  Local<Object> function;
19952  {
19953  Context::Scope scope(context);
19954  function = CompileRun("function foo() {}; foo").As<Object>();
19955  }
19956 
19957  CHECK(function->CreationContext() == context);
19958  CheckContextId(function, 1);
19959 }
19960 
19961 
19963  uint32_t index,
19965  if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
19966 }
19967 
19968 
19970  Local<String> property,
19972  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
19973 }
19974 
19975 
19977  uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
19978  if (index == 42) info.GetReturnValue().Set(1);
19979 }
19980 
19981 
19983  Local<String> property,
19985  if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
19986 }
19987 
19988 
19990  Local<String> property,
19992  if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
19993 }
19994 
19995 
19997  Local<String> property,
19999  info.GetReturnValue().Set(v8_str("yes"));
20000 }
20001 
20002 
20003 TEST(HasOwnProperty) {
20004  LocalContext env;
20005  v8::Isolate* isolate = env->GetIsolate();
20006  v8::HandleScope scope(isolate);
20007  { // Check normal properties and defined getters.
20008  Handle<Value> value = CompileRun(
20009  "function Foo() {"
20010  " this.foo = 11;"
20011  " this.__defineGetter__('baz', function() { return 1; });"
20012  "};"
20013  "function Bar() { "
20014  " this.bar = 13;"
20015  " this.__defineGetter__('bla', function() { return 2; });"
20016  "};"
20017  "Bar.prototype = new Foo();"
20018  "new Bar();");
20019  CHECK(value->IsObject());
20020  Handle<Object> object = value->ToObject();
20021  CHECK(object->Has(v8_str("foo")));
20022  CHECK(!object->HasOwnProperty(v8_str("foo")));
20023  CHECK(object->HasOwnProperty(v8_str("bar")));
20024  CHECK(object->Has(v8_str("baz")));
20025  CHECK(!object->HasOwnProperty(v8_str("baz")));
20026  CHECK(object->HasOwnProperty(v8_str("bla")));
20027  }
20028  { // Check named getter interceptors.
20029  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20030  templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter);
20031  Handle<Object> instance = templ->NewInstance();
20032  CHECK(!instance->HasOwnProperty(v8_str("42")));
20033  CHECK(instance->HasOwnProperty(v8_str("foo")));
20034  CHECK(!instance->HasOwnProperty(v8_str("bar")));
20035  }
20036  { // Check indexed getter interceptors.
20037  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20038  templ->SetIndexedPropertyHandler(HasOwnPropertyIndexedPropertyGetter);
20039  Handle<Object> instance = templ->NewInstance();
20040  CHECK(instance->HasOwnProperty(v8_str("42")));
20041  CHECK(!instance->HasOwnProperty(v8_str("43")));
20042  CHECK(!instance->HasOwnProperty(v8_str("foo")));
20043  }
20044  { // Check named query interceptors.
20045  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20046  templ->SetNamedPropertyHandler(0, 0, HasOwnPropertyNamedPropertyQuery);
20047  Handle<Object> instance = templ->NewInstance();
20048  CHECK(instance->HasOwnProperty(v8_str("foo")));
20049  CHECK(!instance->HasOwnProperty(v8_str("bar")));
20050  }
20051  { // Check indexed query interceptors.
20052  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20053  templ->SetIndexedPropertyHandler(0, 0, HasOwnPropertyIndexedPropertyQuery);
20054  Handle<Object> instance = templ->NewInstance();
20055  CHECK(instance->HasOwnProperty(v8_str("42")));
20056  CHECK(!instance->HasOwnProperty(v8_str("41")));
20057  }
20058  { // Check callbacks.
20059  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20060  templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
20061  Handle<Object> instance = templ->NewInstance();
20062  CHECK(instance->HasOwnProperty(v8_str("foo")));
20063  CHECK(!instance->HasOwnProperty(v8_str("bar")));
20064  }
20065  { // Check that query wins on disagreement.
20066  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20067  templ->SetNamedPropertyHandler(HasOwnPropertyNamedPropertyGetter,
20068  0,
20070  Handle<Object> instance = templ->NewInstance();
20071  CHECK(!instance->HasOwnProperty(v8_str("foo")));
20072  CHECK(instance->HasOwnProperty(v8_str("bar")));
20073  }
20074 }
20075 
20076 
20077 TEST(IndexedInterceptorWithStringProto) {
20078  v8::Isolate* isolate = CcTest::isolate();
20079  v8::HandleScope scope(isolate);
20080  Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20081  templ->SetIndexedPropertyHandler(NULL,
20082  NULL,
20084  LocalContext context;
20085  context->Global()->Set(v8_str("obj"), templ->NewInstance());
20086  CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
20087  // These should be intercepted.
20088  CHECK(CompileRun("42 in obj")->BooleanValue());
20089  CHECK(CompileRun("'42' in obj")->BooleanValue());
20090  // These should fall through to the String prototype.
20091  CHECK(CompileRun("0 in obj")->BooleanValue());
20092  CHECK(CompileRun("'0' in obj")->BooleanValue());
20093  // And these should both fail.
20094  CHECK(!CompileRun("32 in obj")->BooleanValue());
20095  CHECK(!CompileRun("'32' in obj")->BooleanValue());
20096 }
20097 
20098 
20100  Handle<Value> result = CompileRun("eval('42')");
20101  CHECK_EQ(42, result->Int32Value());
20102  result = CompileRun("(function(e) { return e('42'); })(eval)");
20103  CHECK_EQ(42, result->Int32Value());
20104  result = CompileRun("var f = new Function('return 42'); f()");
20105  CHECK_EQ(42, result->Int32Value());
20106 }
20107 
20108 
20110  TryCatch try_catch;
20111 
20112  Handle<Value> result = CompileRun("eval('42')");
20113  CHECK(result.IsEmpty());
20114  CHECK(try_catch.HasCaught());
20115  try_catch.Reset();
20116 
20117  result = CompileRun("(function(e) { return e('42'); })(eval)");
20118  CHECK(result.IsEmpty());
20119  CHECK(try_catch.HasCaught());
20120  try_catch.Reset();
20121 
20122  result = CompileRun("var f = new Function('return 42'); f()");
20123  CHECK(result.IsEmpty());
20124  CHECK(try_catch.HasCaught());
20125 }
20126 
20127 
20128 bool CodeGenerationAllowed(Local<Context> context) {
20130  return true;
20131 }
20132 
20133 
20134 bool CodeGenerationDisallowed(Local<Context> context) {
20136  return false;
20137 }
20138 
20139 
20140 THREADED_TEST(AllowCodeGenFromStrings) {
20141  LocalContext context;
20142  v8::HandleScope scope(context->GetIsolate());
20143 
20144  // eval and the Function constructor allowed by default.
20147 
20148  // Disallow eval and the Function constructor.
20149  context->AllowCodeGenerationFromStrings(false);
20152 
20153  // Allow again.
20154  context->AllowCodeGenerationFromStrings(true);
20156 
20157  // Disallow but setting a global callback that will allow the calls.
20158  context->AllowCodeGenerationFromStrings(false);
20159  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
20162 
20163  // Set a callback that disallows the code generation.
20164  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
20167 }
20168 
20169 
20170 TEST(SetErrorMessageForCodeGenFromStrings) {
20171  LocalContext context;
20172  v8::HandleScope scope(context->GetIsolate());
20173  TryCatch try_catch;
20174 
20175  Handle<String> message = v8_str("Message") ;
20176  Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
20177  V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
20178  context->AllowCodeGenerationFromStrings(false);
20180  Handle<Value> result = CompileRun("eval('42')");
20181  CHECK(result.IsEmpty());
20182  CHECK(try_catch.HasCaught());
20183  Handle<String> actual_message = try_catch.Message()->Get();
20184  CHECK(expected_message->Equals(actual_message));
20185 }
20186 
20187 
20188 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
20189 }
20190 
20191 
20192 THREADED_TEST(CallAPIFunctionOnNonObject) {
20193  LocalContext context;
20194  v8::Isolate* isolate = context->GetIsolate();
20195  v8::HandleScope scope(isolate);
20196  Handle<FunctionTemplate> templ =
20197  v8::FunctionTemplate::New(isolate, NonObjectThis);
20198  Handle<Function> function = templ->GetFunction();
20199  context->Global()->Set(v8_str("f"), function);
20200  TryCatch try_catch;
20201  CompileRun("f.call(2)");
20202 }
20203 
20204 
20205 // Regression test for issue 1470.
20206 THREADED_TEST(ReadOnlyIndexedProperties) {
20207  v8::Isolate* isolate = CcTest::isolate();
20208  v8::HandleScope scope(isolate);
20209  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
20210 
20211  LocalContext context;
20212  Local<v8::Object> obj = templ->NewInstance();
20213  context->Global()->Set(v8_str("obj"), obj);
20214  obj->Set(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20215  obj->Set(v8_str("1"), v8_str("foobar"));
20216  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("1")));
20217  obj->Set(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
20218  obj->Set(v8_num(2), v8_str("foobar"));
20219  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_num(2)));
20220 
20221  // Test non-smi case.
20222  obj->Set(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
20223  obj->Set(v8_str("2000000000"), v8_str("foobar"));
20224  CHECK_EQ(v8_str("DONT_CHANGE"), obj->Get(v8_str("2000000000")));
20225 }
20226 
20227 
20228 THREADED_TEST(Regress1516) {
20229  LocalContext context;
20230  v8::HandleScope scope(context->GetIsolate());
20231 
20232  { v8::HandleScope temp_scope(context->GetIsolate());
20233  CompileRun("({'a': 0})");
20234  }
20235 
20236  int elements;
20237  { i::MapCache* map_cache =
20238  i::MapCache::cast(CcTest::i_isolate()->context()->map_cache());
20239  elements = map_cache->NumberOfElements();
20240  CHECK_LE(1, elements);
20241  }
20242 
20245  { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache();
20246  if (raw_map_cache != CcTest::heap()->undefined_value()) {
20247  i::MapCache* map_cache = i::MapCache::cast(raw_map_cache);
20248  CHECK_GT(elements, map_cache->NumberOfElements());
20249  }
20250  }
20251 }
20252 
20253 
20254 static bool BlockProtoNamedSecurityTestCallback(Local<v8::Object> global,
20255  Local<Value> name,
20256  v8::AccessType type,
20257  Local<Value> data) {
20258  // Only block read access to __proto__.
20259  if (type == v8::ACCESS_GET &&
20260  name->IsString() &&
20261  name->ToString()->Length() == 9 &&
20262  name->ToString()->Utf8Length() == 9) {
20263  char buffer[10];
20264  CHECK_EQ(10, name->ToString()->WriteUtf8(buffer));
20265  return strncmp(buffer, "__proto__", 9) != 0;
20266  }
20267 
20268  return true;
20269 }
20270 
20271 
20272 THREADED_TEST(Regress93759) {
20273  v8::Isolate* isolate = CcTest::isolate();
20274  HandleScope scope(isolate);
20275 
20276  // Template for object with security check.
20277  Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
20278  // We don't do indexing, so any callback can be used for that.
20279  no_proto_template->SetAccessCheckCallbacks(
20280  BlockProtoNamedSecurityTestCallback,
20281  IndexedSecurityTestCallback);
20282 
20283  // Templates for objects with hidden prototypes and possibly security check.
20284  Local<FunctionTemplate> hidden_proto_template =
20285  v8::FunctionTemplate::New(isolate);
20286  hidden_proto_template->SetHiddenPrototype(true);
20287 
20288  Local<FunctionTemplate> protected_hidden_proto_template =
20289  v8::FunctionTemplate::New(isolate);
20290  protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
20291  BlockProtoNamedSecurityTestCallback,
20292  IndexedSecurityTestCallback);
20293  protected_hidden_proto_template->SetHiddenPrototype(true);
20294 
20295  // Context for "foreign" objects used in test.
20296  Local<Context> context = v8::Context::New(isolate);
20297  context->Enter();
20298 
20299  // Plain object, no security check.
20300  Local<Object> simple_object = Object::New(isolate);
20301 
20302  // Object with explicit security check.
20303  Local<Object> protected_object =
20304  no_proto_template->NewInstance();
20305 
20306  // JSGlobalProxy object, always have security check.
20307  Local<Object> proxy_object =
20308  context->Global();
20309 
20310  // Global object, the prototype of proxy_object. No security checks.
20311  Local<Object> global_object =
20312  proxy_object->GetPrototype()->ToObject();
20313 
20314  // Hidden prototype without security check.
20315  Local<Object> hidden_prototype =
20316  hidden_proto_template->GetFunction()->NewInstance();
20317  Local<Object> object_with_hidden =
20318  Object::New(isolate);
20319  object_with_hidden->SetPrototype(hidden_prototype);
20320 
20321  // Hidden prototype with security check on the hidden prototype.
20322  Local<Object> protected_hidden_prototype =
20323  protected_hidden_proto_template->GetFunction()->NewInstance();
20324  Local<Object> object_with_protected_hidden =
20325  Object::New(isolate);
20326  object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
20327 
20328  context->Exit();
20329 
20330  // Template for object for second context. Values to test are put on it as
20331  // properties.
20332  Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
20333  global_template->Set(v8_str("simple"), simple_object);
20334  global_template->Set(v8_str("protected"), protected_object);
20335  global_template->Set(v8_str("global"), global_object);
20336  global_template->Set(v8_str("proxy"), proxy_object);
20337  global_template->Set(v8_str("hidden"), object_with_hidden);
20338  global_template->Set(v8_str("phidden"), object_with_protected_hidden);
20339 
20340  LocalContext context2(NULL, global_template);
20341 
20342  Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
20343  CHECK(result1->Equals(simple_object->GetPrototype()));
20344 
20345  Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
20346  CHECK(result2->Equals(Undefined(isolate)));
20347 
20348  Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
20349  CHECK(result3->Equals(global_object->GetPrototype()));
20350 
20351  Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
20352  CHECK(result4->Equals(Undefined(isolate)));
20353 
20354  Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
20355  CHECK(result5->Equals(
20356  object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
20357 
20358  Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
20359  CHECK(result6->Equals(Undefined(isolate)));
20360 }
20361 
20362 
20363 THREADED_TEST(Regress125988) {
20365  Handle<FunctionTemplate> intercept = FunctionTemplate::New(CcTest::isolate());
20367  LocalContext env;
20368  env->Global()->Set(v8_str("Intercept"), intercept->GetFunction());
20369  CompileRun("var a = new Object();"
20370  "var b = new Intercept();"
20371  "var c = new Object();"
20372  "c.__proto__ = b;"
20373  "b.__proto__ = a;"
20374  "a.x = 23;"
20375  "for (var i = 0; i < 3; i++) c.x;");
20376  ExpectBoolean("c.hasOwnProperty('x')", false);
20377  ExpectInt32("c.x", 23);
20378  CompileRun("a.y = 42;"
20379  "for (var i = 0; i < 3; i++) c.x;");
20380  ExpectBoolean("c.hasOwnProperty('x')", false);
20381  ExpectInt32("c.x", 23);
20382  ExpectBoolean("c.hasOwnProperty('y')", false);
20383  ExpectInt32("c.y", 42);
20384 }
20385 
20386 
20387 static void TestReceiver(Local<Value> expected_result,
20388  Local<Value> expected_receiver,
20389  const char* code) {
20390  Local<Value> result = CompileRun(code);
20391  CHECK(result->IsObject());
20392  CHECK(expected_receiver->Equals(result->ToObject()->Get(1)));
20393  CHECK(expected_result->Equals(result->ToObject()->Get(0)));
20394 }
20395 
20396 
20397 THREADED_TEST(ForeignFunctionReceiver) {
20398  v8::Isolate* isolate = CcTest::isolate();
20399  HandleScope scope(isolate);
20400 
20401  // Create two contexts with different "id" properties ('i' and 'o').
20402  // Call a function both from its own context and from a the foreign
20403  // context, and see what "this" is bound to (returning both "this"
20404  // and "this.id" for comparison).
20405 
20406  Local<Context> foreign_context = v8::Context::New(isolate);
20407  foreign_context->Enter();
20408  Local<Value> foreign_function =
20409  CompileRun("function func() { return { 0: this.id, "
20410  " 1: this, "
20411  " toString: function() { "
20412  " return this[0];"
20413  " }"
20414  " };"
20415  "}"
20416  "var id = 'i';"
20417  "func;");
20418  CHECK(foreign_function->IsFunction());
20419  foreign_context->Exit();
20420 
20421  LocalContext context;
20422 
20423  Local<String> password = v8_str("Password");
20424  // Don't get hit by security checks when accessing foreign_context's
20425  // global receiver (aka. global proxy).
20426  context->SetSecurityToken(password);
20427  foreign_context->SetSecurityToken(password);
20428 
20429  Local<String> i = v8_str("i");
20430  Local<String> o = v8_str("o");
20431  Local<String> id = v8_str("id");
20432 
20433  CompileRun("function ownfunc() { return { 0: this.id, "
20434  " 1: this, "
20435  " toString: function() { "
20436  " return this[0];"
20437  " }"
20438  " };"
20439  "}"
20440  "var id = 'o';"
20441  "ownfunc");
20442  context->Global()->Set(v8_str("func"), foreign_function);
20443 
20444  // Sanity check the contexts.
20445  CHECK(i->Equals(foreign_context->Global()->Get(id)));
20446  CHECK(o->Equals(context->Global()->Get(id)));
20447 
20448  // Checking local function's receiver.
20449  // Calling function using its call/apply methods.
20450  TestReceiver(o, context->Global(), "ownfunc.call()");
20451  TestReceiver(o, context->Global(), "ownfunc.apply()");
20452  // Making calls through built-in functions.
20453  TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
20454  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
20455  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
20456  CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
20457  // Calling with environment record as base.
20458  TestReceiver(o, context->Global(), "ownfunc()");
20459  // Calling with no base.
20460  TestReceiver(o, context->Global(), "(1,ownfunc)()");
20461 
20462  // Checking foreign function return value.
20463  // Calling function using its call/apply methods.
20464  TestReceiver(i, foreign_context->Global(), "func.call()");
20465  TestReceiver(i, foreign_context->Global(), "func.apply()");
20466  // Calling function using another context's call/apply methods.
20467  TestReceiver(i, foreign_context->Global(),
20468  "Function.prototype.call.call(func)");
20469  TestReceiver(i, foreign_context->Global(),
20470  "Function.prototype.call.apply(func)");
20471  TestReceiver(i, foreign_context->Global(),
20472  "Function.prototype.apply.call(func)");
20473  TestReceiver(i, foreign_context->Global(),
20474  "Function.prototype.apply.apply(func)");
20475  // Making calls through built-in functions.
20476  TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
20477  // ToString(func()) is func()[0], i.e., the returned this.id.
20478  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
20479  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
20480  CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
20481 
20482  // Calling with environment record as base.
20483  TestReceiver(i, foreign_context->Global(), "func()");
20484  // Calling with no base.
20485  TestReceiver(i, foreign_context->Global(), "(1,func)()");
20486 }
20487 
20488 
20489 uint8_t callback_fired = 0;
20490 
20491 
20493  i::OS::Print("Firing callback 1.\n");
20494  callback_fired ^= 1; // Toggle first bit.
20495 }
20496 
20497 
20499  i::OS::Print("Firing callback 2.\n");
20500  callback_fired ^= 2; // Toggle second bit.
20501 }
20502 
20503 
20505  int32_t level = args[0]->Int32Value();
20506  if (level < 3) {
20507  level++;
20508  i::OS::Print("Entering recursion level %d.\n", level);
20509  char script[64];
20510  i::Vector<char> script_vector(script, sizeof(script));
20511  i::OS::SNPrintF(script_vector, "recursion(%d)", level);
20512  CompileRun(script_vector.start());
20513  i::OS::Print("Leaving recursion level %d.\n", level);
20514  CHECK_EQ(0, callback_fired);
20515  } else {
20516  i::OS::Print("Recursion ends.\n");
20517  CHECK_EQ(0, callback_fired);
20518  }
20519 }
20520 
20521 
20523  LocalContext env;
20524  v8::HandleScope scope(env->GetIsolate());
20525  v8::Handle<v8::FunctionTemplate> recursive_runtime =
20527  env->Global()->Set(v8_str("recursion"),
20528  recursive_runtime->GetFunction());
20529  // Adding the same callback a second time has no effect.
20533  i::OS::Print("--- Script (1) ---\n");
20534  Local<Script> script = v8::Script::Compile(
20535  v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
20536  script->Run();
20537  CHECK_EQ(3, callback_fired);
20538 
20539  i::OS::Print("\n--- Script (2) ---\n");
20540  callback_fired = 0;
20542  script->Run();
20543  CHECK_EQ(2, callback_fired);
20544 
20545  i::OS::Print("\n--- Function ---\n");
20546  callback_fired = 0;
20547  Local<Function> recursive_function =
20548  Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
20549  v8::Handle<Value> args[] = { v8_num(0) };
20550  recursive_function->Call(env->Global(), 1, args);
20551  CHECK_EQ(2, callback_fired);
20552 }
20553 
20554 
20557  CompileRun("1+1;");
20558 }
20559 
20560 
20563  CompileRun("throw 'second exception';");
20564 }
20565 
20566 
20567 TEST(CallCompletedCallbackOneException) {
20568  LocalContext env;
20569  v8::HandleScope scope(env->GetIsolate());
20571  CompileRun("throw 'exception';");
20572 }
20573 
20574 
20575 TEST(CallCompletedCallbackTwoExceptions) {
20576  LocalContext env;
20577  v8::HandleScope scope(env->GetIsolate());
20579  CompileRun("throw 'first exception';");
20580 }
20581 
20582 
20583 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
20584  v8::HandleScope scope(info.GetIsolate());
20585  CompileRun("ext1Calls++;");
20586 }
20587 
20588 
20589 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
20590  v8::HandleScope scope(info.GetIsolate());
20591  CompileRun("ext2Calls++;");
20592 }
20593 
20594 
20595 TEST(EnqueueMicrotask) {
20596  LocalContext env;
20597  v8::HandleScope scope(env->GetIsolate());
20598  CompileRun(
20599  "var ext1Calls = 0;"
20600  "var ext2Calls = 0;");
20601  CompileRun("1+1;");
20602  CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
20603  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20604 
20606  Function::New(env->GetIsolate(), MicrotaskOne));
20607  CompileRun("1+1;");
20608  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
20609  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20610 
20612  Function::New(env->GetIsolate(), MicrotaskOne));
20614  Function::New(env->GetIsolate(), MicrotaskTwo));
20615  CompileRun("1+1;");
20616  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20617  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
20618 
20620  Function::New(env->GetIsolate(), MicrotaskTwo));
20621  CompileRun("1+1;");
20622  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20623  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
20624 
20625  CompileRun("1+1;");
20626  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20627  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
20628 }
20629 
20630 
20631 TEST(SetAutorunMicrotasks) {
20632  LocalContext env;
20633  v8::HandleScope scope(env->GetIsolate());
20634  CompileRun(
20635  "var ext1Calls = 0;"
20636  "var ext2Calls = 0;");
20637  CompileRun("1+1;");
20638  CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
20639  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20640 
20642  Function::New(env->GetIsolate(), MicrotaskOne));
20643  CompileRun("1+1;");
20644  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
20645  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20646 
20647  V8::SetAutorunMicrotasks(env->GetIsolate(), false);
20649  Function::New(env->GetIsolate(), MicrotaskOne));
20651  Function::New(env->GetIsolate(), MicrotaskTwo));
20652  CompileRun("1+1;");
20653  CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
20654  CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
20655 
20656  V8::RunMicrotasks(env->GetIsolate());
20657  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20658  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
20659 
20661  Function::New(env->GetIsolate(), MicrotaskTwo));
20662  CompileRun("1+1;");
20663  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20664  CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
20665 
20666  V8::RunMicrotasks(env->GetIsolate());
20667  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20668  CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
20669 
20670  V8::SetAutorunMicrotasks(env->GetIsolate(), true);
20672  Function::New(env->GetIsolate(), MicrotaskTwo));
20673  CompileRun("1+1;");
20674  CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
20675  CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
20676 }
20677 
20678 
20679 static int probes_counter = 0;
20680 static int misses_counter = 0;
20681 static int updates_counter = 0;
20682 
20683 
20684 static int* LookupCounter(const char* name) {
20685  if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
20686  return &probes_counter;
20687  } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
20688  return &misses_counter;
20689  } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
20690  return &updates_counter;
20691  }
20692  return NULL;
20693 }
20694 
20695 
20696 static const char* kMegamorphicTestProgram =
20697  "function ClassA() { };"
20698  "function ClassB() { };"
20699  "ClassA.prototype.foo = function() { };"
20700  "ClassB.prototype.foo = function() { };"
20701  "function fooify(obj) { obj.foo(); };"
20702  "var a = new ClassA();"
20703  "var b = new ClassB();"
20704  "for (var i = 0; i < 10000; i++) {"
20705  " fooify(a);"
20706  " fooify(b);"
20707  "}";
20708 
20709 
20710 static void StubCacheHelper(bool primary) {
20711  V8::SetCounterFunction(LookupCounter);
20712  USE(kMegamorphicTestProgram);
20713 #ifdef DEBUG
20714  i::FLAG_native_code_counters = true;
20715  if (primary) {
20716  i::FLAG_test_primary_stub_cache = true;
20717  } else {
20718  i::FLAG_test_secondary_stub_cache = true;
20719  }
20720  i::FLAG_crankshaft = false;
20721  LocalContext env;
20722  v8::HandleScope scope(env->GetIsolate());
20723  int initial_probes = probes_counter;
20724  int initial_misses = misses_counter;
20725  int initial_updates = updates_counter;
20726  CompileRun(kMegamorphicTestProgram);
20727  int probes = probes_counter - initial_probes;
20728  int misses = misses_counter - initial_misses;
20729  int updates = updates_counter - initial_updates;
20730  CHECK_LT(updates, 10);
20731  CHECK_LT(misses, 10);
20732  // TODO(verwaest): Update this test to overflow the degree of polymorphism
20733  // before megamorphism. The number of probes will only work once we teach the
20734  // serializer to embed references to counters in the stubs, given that the
20735  // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
20736  CHECK_GE(probes, 0);
20737 #endif
20738 }
20739 
20740 
20741 TEST(SecondaryStubCache) {
20742  StubCacheHelper(true);
20743 }
20744 
20745 
20746 TEST(PrimaryStubCache) {
20747  StubCacheHelper(false);
20748 }
20749 
20750 
20751 static int cow_arrays_created_runtime = 0;
20752 
20753 
20754 static int* LookupCounterCOWArrays(const char* name) {
20755  if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
20756  return &cow_arrays_created_runtime;
20757  }
20758  return NULL;
20759 }
20760 
20761 
20762 TEST(CheckCOWArraysCreatedRuntimeCounter) {
20763  V8::SetCounterFunction(LookupCounterCOWArrays);
20764 #ifdef DEBUG
20765  i::FLAG_native_code_counters = true;
20766  LocalContext env;
20767  v8::HandleScope scope(env->GetIsolate());
20768  int initial_cow_arrays = cow_arrays_created_runtime;
20769  CompileRun("var o = [1, 2, 3];");
20770  CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
20771  CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
20772  CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
20773  CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
20774  CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
20775 #endif
20776 }
20777 
20778 
20779 TEST(StaticGetters) {
20780  LocalContext context;
20781  i::Factory* factory = CcTest::i_isolate()->factory();
20782  v8::Isolate* isolate = CcTest::isolate();
20783  v8::HandleScope scope(isolate);
20784  i::Handle<i::Object> undefined_value = factory->undefined_value();
20785  CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
20786  i::Handle<i::Object> null_value = factory->null_value();
20787  CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
20788  i::Handle<i::Object> true_value = factory->true_value();
20789  CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
20790  i::Handle<i::Object> false_value = factory->false_value();
20791  CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
20792 }
20793 
20794 
20795 UNINITIALIZED_TEST(IsolateEmbedderData) {
20797  v8::Isolate* isolate = v8::Isolate::New();
20798  isolate->Enter();
20799  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
20800  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20801  CHECK_EQ(NULL, isolate->GetData(slot));
20802  CHECK_EQ(NULL, i_isolate->GetData(slot));
20803  }
20804  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20805  void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20806  isolate->SetData(slot, data);
20807  }
20808  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20809  void* data = reinterpret_cast<void*>(0xacce55ed + slot);
20810  CHECK_EQ(data, isolate->GetData(slot));
20811  CHECK_EQ(data, i_isolate->GetData(slot));
20812  }
20813  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20814  void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20815  isolate->SetData(slot, data);
20816  }
20817  for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
20818  void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
20819  CHECK_EQ(data, isolate->GetData(slot));
20820  CHECK_EQ(data, i_isolate->GetData(slot));
20821  }
20822  isolate->Exit();
20823  isolate->Dispose();
20824 }
20825 
20826 
20827 TEST(StringEmpty) {
20828  LocalContext context;
20829  i::Factory* factory = CcTest::i_isolate()->factory();
20830  v8::Isolate* isolate = CcTest::isolate();
20831  v8::HandleScope scope(isolate);
20832  i::Handle<i::Object> empty_string = factory->empty_string();
20833  CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
20834 }
20835 
20836 
20837 static int instance_checked_getter_count = 0;
20838 static void InstanceCheckedGetter(
20839  Local<String> name,
20841  CHECK_EQ(name, v8_str("foo"));
20842  instance_checked_getter_count++;
20843  info.GetReturnValue().Set(v8_num(11));
20844 }
20845 
20846 
20847 static int instance_checked_setter_count = 0;
20848 static void InstanceCheckedSetter(Local<String> name,
20849  Local<Value> value,
20850  const v8::PropertyCallbackInfo<void>& info) {
20851  CHECK_EQ(name, v8_str("foo"));
20852  CHECK_EQ(value, v8_num(23));
20853  instance_checked_setter_count++;
20854 }
20855 
20856 
20857 static void CheckInstanceCheckedResult(int getters,
20858  int setters,
20859  bool expects_callbacks,
20860  TryCatch* try_catch) {
20861  if (expects_callbacks) {
20862  CHECK(!try_catch->HasCaught());
20863  CHECK_EQ(getters, instance_checked_getter_count);
20864  CHECK_EQ(setters, instance_checked_setter_count);
20865  } else {
20866  CHECK(try_catch->HasCaught());
20867  CHECK_EQ(0, instance_checked_getter_count);
20868  CHECK_EQ(0, instance_checked_setter_count);
20869  }
20870  try_catch->Reset();
20871 }
20872 
20873 
20874 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
20875  instance_checked_getter_count = 0;
20876  instance_checked_setter_count = 0;
20877  TryCatch try_catch;
20878 
20879  // Test path through generic runtime code.
20880  CompileRun("obj.foo");
20881  CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
20882  CompileRun("obj.foo = 23");
20883  CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
20884 
20885  // Test path through generated LoadIC and StoredIC.
20886  CompileRun("function test_get(o) { o.foo; }"
20887  "test_get(obj);");
20888  CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
20889  CompileRun("test_get(obj);");
20890  CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
20891  CompileRun("test_get(obj);");
20892  CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
20893  CompileRun("function test_set(o) { o.foo = 23; }"
20894  "test_set(obj);");
20895  CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
20896  CompileRun("test_set(obj);");
20897  CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
20898  CompileRun("test_set(obj);");
20899  CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
20900 
20901  // Test path through optimized code.
20902  CompileRun("%OptimizeFunctionOnNextCall(test_get);"
20903  "test_get(obj);");
20904  CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
20905  CompileRun("%OptimizeFunctionOnNextCall(test_set);"
20906  "test_set(obj);");
20907  CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
20908 
20909  // Cleanup so that closures start out fresh in next check.
20910  CompileRun("%DeoptimizeFunction(test_get);"
20911  "%ClearFunctionTypeFeedback(test_get);"
20912  "%DeoptimizeFunction(test_set);"
20913  "%ClearFunctionTypeFeedback(test_set);");
20914 }
20915 
20916 
20917 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
20918  v8::internal::FLAG_allow_natives_syntax = true;
20919  LocalContext context;
20920  v8::HandleScope scope(context->GetIsolate());
20921 
20922  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
20923  Local<ObjectTemplate> inst = templ->InstanceTemplate();
20924  inst->SetAccessor(v8_str("foo"),
20925  InstanceCheckedGetter, InstanceCheckedSetter,
20926  Handle<Value>(),
20927  v8::DEFAULT,
20928  v8::None,
20929  v8::AccessorSignature::New(context->GetIsolate(), templ));
20930  context->Global()->Set(v8_str("f"), templ->GetFunction());
20931 
20932  printf("Testing positive ...\n");
20933  CompileRun("var obj = new f();");
20934  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20935  CheckInstanceCheckedAccessors(true);
20936 
20937  printf("Testing negative ...\n");
20938  CompileRun("var obj = {};"
20939  "obj.__proto__ = new f();");
20940  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20941  CheckInstanceCheckedAccessors(false);
20942 }
20943 
20944 
20945 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
20946  v8::internal::FLAG_allow_natives_syntax = true;
20947  LocalContext context;
20948  v8::HandleScope scope(context->GetIsolate());
20949 
20950  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
20951  Local<ObjectTemplate> inst = templ->InstanceTemplate();
20953  inst->SetAccessor(v8_str("foo"),
20954  InstanceCheckedGetter, InstanceCheckedSetter,
20955  Handle<Value>(),
20956  v8::DEFAULT,
20957  v8::None,
20958  v8::AccessorSignature::New(context->GetIsolate(), templ));
20959  context->Global()->Set(v8_str("f"), templ->GetFunction());
20960 
20961  printf("Testing positive ...\n");
20962  CompileRun("var obj = new f();");
20963  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20964  CheckInstanceCheckedAccessors(true);
20965 
20966  printf("Testing negative ...\n");
20967  CompileRun("var obj = {};"
20968  "obj.__proto__ = new f();");
20969  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20970  CheckInstanceCheckedAccessors(false);
20971 }
20972 
20973 
20974 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
20975  v8::internal::FLAG_allow_natives_syntax = true;
20976  LocalContext context;
20977  v8::HandleScope scope(context->GetIsolate());
20978 
20979  Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
20980  Local<ObjectTemplate> proto = templ->PrototypeTemplate();
20981  proto->SetAccessor(v8_str("foo"),
20982  InstanceCheckedGetter, InstanceCheckedSetter,
20983  Handle<Value>(),
20984  v8::DEFAULT,
20985  v8::None,
20986  v8::AccessorSignature::New(context->GetIsolate(), templ));
20987  context->Global()->Set(v8_str("f"), templ->GetFunction());
20988 
20989  printf("Testing positive ...\n");
20990  CompileRun("var obj = new f();");
20991  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20992  CheckInstanceCheckedAccessors(true);
20993 
20994  printf("Testing negative ...\n");
20995  CompileRun("var obj = {};"
20996  "obj.__proto__ = new f();");
20997  CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
20998  CheckInstanceCheckedAccessors(false);
20999 
21000  printf("Testing positive with modified prototype chain ...\n");
21001  CompileRun("var obj = new f();"
21002  "var pro = {};"
21003  "pro.__proto__ = obj.__proto__;"
21004  "obj.__proto__ = pro;");
21005  CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
21006  CheckInstanceCheckedAccessors(true);
21007 }
21008 
21009 
21010 TEST(TryFinallyMessage) {
21011  LocalContext context;
21012  v8::HandleScope scope(context->GetIsolate());
21013  {
21014  // Test that the original error message is not lost if there is a
21015  // recursive call into Javascript is done in the finally block, e.g. to
21016  // initialize an IC. (crbug.com/129171)
21017  TryCatch try_catch;
21018  const char* trigger_ic =
21019  "try { \n"
21020  " throw new Error('test'); \n"
21021  "} finally { \n"
21022  " var x = 0; \n"
21023  " x++; \n" // Trigger an IC initialization here.
21024  "} \n";
21025  CompileRun(trigger_ic);
21026  CHECK(try_catch.HasCaught());
21027  Local<Message> message = try_catch.Message();
21028  CHECK(!message.IsEmpty());
21029  CHECK_EQ(2, message->GetLineNumber());
21030  }
21031 
21032  {
21033  // Test that the original exception message is indeed overwritten if
21034  // a new error is thrown in the finally block.
21035  TryCatch try_catch;
21036  const char* throw_again =
21037  "try { \n"
21038  " throw new Error('test'); \n"
21039  "} finally { \n"
21040  " var x = 0; \n"
21041  " x++; \n"
21042  " throw new Error('again'); \n" // This is the new uncaught error.
21043  "} \n";
21044  CompileRun(throw_again);
21045  CHECK(try_catch.HasCaught());
21046  Local<Message> message = try_catch.Message();
21047  CHECK(!message.IsEmpty());
21048  CHECK_EQ(6, message->GetLineNumber());
21049  }
21050 }
21051 
21052 
21053 static void Helper137002(bool do_store,
21054  bool polymorphic,
21055  bool remove_accessor,
21056  bool interceptor) {
21057  LocalContext context;
21058  Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
21059  if (interceptor) {
21060  templ->SetNamedPropertyHandler(FooGetInterceptor, FooSetInterceptor);
21061  } else {
21062  templ->SetAccessor(v8_str("foo"),
21063  GetterWhichReturns42,
21064  SetterWhichSetsYOnThisTo23);
21065  }
21066  context->Global()->Set(v8_str("obj"), templ->NewInstance());
21067 
21068  // Turn monomorphic on slow object with native accessor, then turn
21069  // polymorphic, finally optimize to create negative lookup and fail.
21070  CompileRun(do_store ?
21071  "function f(x) { x.foo = void 0; }" :
21072  "function f(x) { return x.foo; }");
21073  CompileRun("obj.y = void 0;");
21074  if (!interceptor) {
21075  CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
21076  }
21077  CompileRun("obj.__proto__ = null;"
21078  "f(obj); f(obj); f(obj);");
21079  if (polymorphic) {
21080  CompileRun("f({});");
21081  }
21082  CompileRun("obj.y = void 0;"
21083  "%OptimizeFunctionOnNextCall(f);");
21084  if (remove_accessor) {
21085  CompileRun("delete obj.foo;");
21086  }
21087  CompileRun("var result = f(obj);");
21088  if (do_store) {
21089  CompileRun("result = obj.y;");
21090  }
21091  if (remove_accessor && !interceptor) {
21092  CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
21093  } else {
21094  CHECK_EQ(do_store ? 23 : 42,
21095  context->Global()->Get(v8_str("result"))->Int32Value());
21096  }
21097 }
21098 
21099 
21100 THREADED_TEST(Regress137002a) {
21101  i::FLAG_allow_natives_syntax = true;
21102  i::FLAG_compilation_cache = false;
21104  for (int i = 0; i < 16; i++) {
21105  Helper137002(i & 8, i & 4, i & 2, i & 1);
21106  }
21107 }
21108 
21109 
21110 THREADED_TEST(Regress137002b) {
21111  i::FLAG_allow_natives_syntax = true;
21112  LocalContext context;
21113  v8::Isolate* isolate = context->GetIsolate();
21114  v8::HandleScope scope(isolate);
21115  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21116  templ->SetAccessor(v8_str("foo"),
21117  GetterWhichReturns42,
21118  SetterWhichSetsYOnThisTo23);
21119  context->Global()->Set(v8_str("obj"), templ->NewInstance());
21120 
21121  // Turn monomorphic on slow object with native accessor, then just
21122  // delete the property and fail.
21123  CompileRun("function load(x) { return x.foo; }"
21124  "function store(x) { x.foo = void 0; }"
21125  "function keyed_load(x, key) { return x[key]; }"
21126  // Second version of function has a different source (add void 0)
21127  // so that it does not share code with the first version. This
21128  // ensures that the ICs are monomorphic.
21129  "function load2(x) { void 0; return x.foo; }"
21130  "function store2(x) { void 0; x.foo = void 0; }"
21131  "function keyed_load2(x, key) { void 0; return x[key]; }"
21132 
21133  "obj.y = void 0;"
21134  "obj.__proto__ = null;"
21135  "var subobj = {};"
21136  "subobj.y = void 0;"
21137  "subobj.__proto__ = obj;"
21138  "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21139 
21140  // Make the ICs monomorphic.
21141  "load(obj); load(obj);"
21142  "load2(subobj); load2(subobj);"
21143  "store(obj); store(obj);"
21144  "store2(subobj); store2(subobj);"
21145  "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
21146  "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
21147 
21148  // Actually test the shiny new ICs and better not crash. This
21149  // serves as a regression test for issue 142088 as well.
21150  "load(obj);"
21151  "load2(subobj);"
21152  "store(obj);"
21153  "store2(subobj);"
21154  "keyed_load(obj, 'foo');"
21155  "keyed_load2(subobj, 'foo');"
21156 
21157  // Delete the accessor. It better not be called any more now.
21158  "delete obj.foo;"
21159  "obj.y = void 0;"
21160  "subobj.y = void 0;"
21161 
21162  "var load_result = load(obj);"
21163  "var load_result2 = load2(subobj);"
21164  "var keyed_load_result = keyed_load(obj, 'foo');"
21165  "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
21166  "store(obj);"
21167  "store2(subobj);"
21168  "var y_from_obj = obj.y;"
21169  "var y_from_subobj = subobj.y;");
21170  CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
21171  CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
21172  CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
21173  CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
21174  CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
21175  CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
21176 }
21177 
21178 
21179 THREADED_TEST(Regress142088) {
21180  i::FLAG_allow_natives_syntax = true;
21181  LocalContext context;
21182  v8::Isolate* isolate = context->GetIsolate();
21183  v8::HandleScope scope(isolate);
21184  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21185  templ->SetAccessor(v8_str("foo"),
21186  GetterWhichReturns42,
21187  SetterWhichSetsYOnThisTo23);
21188  context->Global()->Set(v8_str("obj"), templ->NewInstance());
21189 
21190  CompileRun("function load(x) { return x.foo; }"
21191  "var o = Object.create(obj);"
21192  "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
21193  "load(o); load(o); load(o); load(o);");
21194 }
21195 
21196 
21197 THREADED_TEST(Regress137496) {
21198  i::FLAG_expose_gc = true;
21199  LocalContext context;
21200  v8::HandleScope scope(context->GetIsolate());
21201 
21202  // Compile a try-finally clause where the finally block causes a GC
21203  // while there still is a message pending for external reporting.
21204  TryCatch try_catch;
21205  try_catch.SetVerbose(true);
21206  CompileRun("try { throw new Error(); } finally { gc(); }");
21207  CHECK(try_catch.HasCaught());
21208 }
21209 
21210 
21211 THREADED_TEST(Regress149912) {
21212  LocalContext context;
21213  v8::HandleScope scope(context->GetIsolate());
21214  Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21216  context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21217  CompileRun("Number.prototype.__proto__ = new Bug; var x = 0; x.foo();");
21218 }
21219 
21220 
21221 THREADED_TEST(Regress157124) {
21222  LocalContext context;
21223  v8::Isolate* isolate = context->GetIsolate();
21224  v8::HandleScope scope(isolate);
21225  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21226  Local<Object> obj = templ->NewInstance();
21227  obj->GetIdentityHash();
21228  obj->DeleteHiddenValue(v8_str("Bug"));
21229 }
21230 
21231 
21232 THREADED_TEST(Regress2535) {
21233  i::FLAG_harmony_collections = true;
21234  LocalContext context;
21235  v8::HandleScope scope(context->GetIsolate());
21236  Local<Value> set_value = CompileRun("new Set();");
21237  Local<Object> set_object(Local<Object>::Cast(set_value));
21238  CHECK_EQ(0, set_object->InternalFieldCount());
21239  Local<Value> map_value = CompileRun("new Map();");
21240  Local<Object> map_object(Local<Object>::Cast(map_value));
21241  CHECK_EQ(0, map_object->InternalFieldCount());
21242 }
21243 
21244 
21245 THREADED_TEST(Regress2746) {
21246  LocalContext context;
21247  v8::Isolate* isolate = context->GetIsolate();
21248  v8::HandleScope scope(isolate);
21249  Local<Object> obj = Object::New(isolate);
21250  Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
21251  obj->SetHiddenValue(key, v8::Undefined(isolate));
21252  Local<Value> value = obj->GetHiddenValue(key);
21253  CHECK(!value.IsEmpty());
21254  CHECK(value->IsUndefined());
21255 }
21256 
21257 
21258 THREADED_TEST(Regress260106) {
21259  LocalContext context;
21260  v8::Isolate* isolate = context->GetIsolate();
21261  v8::HandleScope scope(isolate);
21262  Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
21263  DummyCallHandler);
21264  CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
21265  Local<Function> function = templ->GetFunction();
21266  CHECK(!function.IsEmpty());
21267  CHECK(function->IsFunction());
21268 }
21269 
21270 
21271 THREADED_TEST(JSONParseObject) {
21272  LocalContext context;
21273  HandleScope scope(context->GetIsolate());
21274  Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
21275  Handle<Object> global = context->Global();
21276  global->Set(v8_str("obj"), obj);
21277  ExpectString("JSON.stringify(obj)", "{\"x\":42}");
21278 }
21279 
21280 
21281 THREADED_TEST(JSONParseNumber) {
21282  LocalContext context;
21283  HandleScope scope(context->GetIsolate());
21284  Local<Value> obj = v8::JSON::Parse(v8_str("42"));
21285  Handle<Object> global = context->Global();
21286  global->Set(v8_str("obj"), obj);
21287  ExpectString("JSON.stringify(obj)", "42");
21288 }
21289 
21290 
21291 #if V8_OS_POSIX
21292 class ThreadInterruptTest {
21293  public:
21294  ThreadInterruptTest() : sem_(0), sem_value_(0) { }
21295  ~ThreadInterruptTest() {}
21296 
21297  void RunTest() {
21298  InterruptThread i_thread(this);
21299  i_thread.Start();
21300 
21301  sem_.Wait();
21302  CHECK_EQ(kExpectedValue, sem_value_);
21303  }
21304 
21305  private:
21306  static const int kExpectedValue = 1;
21307 
21308  class InterruptThread : public i::Thread {
21309  public:
21310  explicit InterruptThread(ThreadInterruptTest* test)
21311  : Thread("InterruptThread"), test_(test) {}
21312 
21313  virtual void Run() {
21314  struct sigaction action;
21315 
21316  // Ensure that we'll enter waiting condition
21317  i::OS::Sleep(100);
21318 
21319  // Setup signal handler
21320  memset(&action, 0, sizeof(action));
21321  action.sa_handler = SignalHandler;
21322  sigaction(SIGCHLD, &action, NULL);
21323 
21324  // Send signal
21325  kill(getpid(), SIGCHLD);
21326 
21327  // Ensure that if wait has returned because of error
21328  i::OS::Sleep(100);
21329 
21330  // Set value and signal semaphore
21331  test_->sem_value_ = 1;
21332  test_->sem_.Signal();
21333  }
21334 
21335  static void SignalHandler(int signal) {
21336  }
21337 
21338  private:
21339  ThreadInterruptTest* test_;
21340  };
21341 
21342  i::Semaphore sem_;
21343  volatile int sem_value_;
21344 };
21345 
21346 
21347 THREADED_TEST(SemaphoreInterruption) {
21348  ThreadInterruptTest().RunTest();
21349 }
21350 
21351 
21352 #endif // V8_OS_POSIX
21353 
21354 
21355 static bool NamedAccessAlwaysBlocked(Local<v8::Object> global,
21356  Local<Value> name,
21357  v8::AccessType type,
21358  Local<Value> data) {
21359  i::PrintF("Named access blocked.\n");
21360  return false;
21361 }
21362 
21363 
21364 static bool IndexAccessAlwaysBlocked(Local<v8::Object> global,
21365  uint32_t key,
21366  v8::AccessType type,
21367  Local<Value> data) {
21368  i::PrintF("Indexed access blocked.\n");
21369  return false;
21370 }
21371 
21372 
21374  CHECK(false);
21375 }
21376 
21377 
21378 TEST(JSONStringifyAccessCheck) {
21380  v8::Isolate* isolate = CcTest::isolate();
21381  v8::HandleScope scope(isolate);
21382 
21383  // Create an ObjectTemplate for global objects and install access
21384  // check callbacks that will block access.
21385  v8::Handle<v8::ObjectTemplate> global_template =
21386  v8::ObjectTemplate::New(isolate);
21387  global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21388  IndexAccessAlwaysBlocked);
21389 
21390  // Create a context and set an x property on it's global object.
21391  LocalContext context0(NULL, global_template);
21392  v8::Handle<v8::Object> global0 = context0->Global();
21393  global0->Set(v8_str("x"), v8_num(42));
21394  ExpectString("JSON.stringify(this)", "{\"x\":42}");
21395 
21396  for (int i = 0; i < 2; i++) {
21397  if (i == 1) {
21398  // Install a toJSON function on the second run.
21401 
21402  global0->Set(v8_str("toJSON"), toJSON->GetFunction());
21403  }
21404  // Create a context with a different security token so that the
21405  // failed access check callback will be called on each access.
21406  LocalContext context1(NULL, global_template);
21407  context1->Global()->Set(v8_str("other"), global0);
21408 
21409  ExpectString("JSON.stringify(other)", "{}");
21410  ExpectString("JSON.stringify({ 'a' : other, 'b' : ['c'] })",
21411  "{\"a\":{},\"b\":[\"c\"]}");
21412  ExpectString("JSON.stringify([other, 'b', 'c'])",
21413  "[{},\"b\",\"c\"]");
21414 
21415  v8::Handle<v8::Array> array = v8::Array::New(isolate, 2);
21416  array->Set(0, v8_str("a"));
21417  array->Set(1, v8_str("b"));
21418  context1->Global()->Set(v8_str("array"), array);
21419  ExpectString("JSON.stringify(array)", "[\"a\",\"b\"]");
21420  array->TurnOnAccessCheck();
21421  ExpectString("JSON.stringify(array)", "[]");
21422  ExpectString("JSON.stringify([array])", "[[]]");
21423  ExpectString("JSON.stringify({'a' : array})", "{\"a\":[]}");
21424  }
21425 }
21426 
21427 
21430 
21431 
21432 // Failed access check callback that performs a GC on each invocation.
21433 void FailedAccessCheckThrows(Local<v8::Object> target,
21434  v8::AccessType type,
21435  Local<v8::Value> data) {
21436  access_check_fail_thrown = true;
21437  i::PrintF("Access check failed. Error thrown.\n");
21439  v8::Exception::Error(v8_str("cross context")));
21440 }
21441 
21442 
21444  for (int i = 0; i < args.Length(); i++) {
21445  i::PrintF("%s\n", *String::Utf8Value(args[i]));
21446  }
21447  catch_callback_called = true;
21448 }
21449 
21450 
21452  args[0]->ToObject()->HasOwnProperty(args[1]->ToString());
21453 }
21454 
21455 
21456 void CheckCorrectThrow(const char* script) {
21457  // Test that the script, when wrapped into a try-catch, triggers the catch
21458  // clause due to failed access check throwing an exception.
21459  // The subsequent try-catch should run without any exception.
21460  access_check_fail_thrown = false;
21461  catch_callback_called = false;
21462  i::ScopedVector<char> source(1024);
21463  i::OS::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
21464  CompileRun(source.start());
21465  CHECK(access_check_fail_thrown);
21466  CHECK(catch_callback_called);
21467 
21468  access_check_fail_thrown = false;
21469  catch_callback_called = false;
21470  CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
21471  CHECK(!access_check_fail_thrown);
21472  CHECK(!catch_callback_called);
21473 }
21474 
21475 
21476 TEST(AccessCheckThrows) {
21477  i::FLAG_allow_natives_syntax = true;
21480  v8::Isolate* isolate = CcTest::isolate();
21481  v8::HandleScope scope(isolate);
21482 
21483  // Create an ObjectTemplate for global objects and install access
21484  // check callbacks that will block access.
21485  v8::Handle<v8::ObjectTemplate> global_template =
21486  v8::ObjectTemplate::New(isolate);
21487  global_template->SetAccessCheckCallbacks(NamedAccessAlwaysBlocked,
21488  IndexAccessAlwaysBlocked);
21489 
21490  // Create a context and set an x property on it's global object.
21491  LocalContext context0(NULL, global_template);
21492  context0->Global()->Set(v8_str("x"), v8_num(42));
21493  v8::Handle<v8::Object> global0 = context0->Global();
21494 
21495  // Create a context with a different security token so that the
21496  // failed access check callback will be called on each access.
21497  LocalContext context1(NULL, global_template);
21498  context1->Global()->Set(v8_str("other"), global0);
21499 
21500  v8::Handle<v8::FunctionTemplate> catcher_fun =
21502  context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
21503 
21504  v8::Handle<v8::FunctionTemplate> has_own_property_fun =
21506  context1->Global()->Set(v8_str("has_own_property"),
21507  has_own_property_fun->GetFunction());
21508 
21509  { v8::TryCatch try_catch;
21510  access_check_fail_thrown = false;
21511  CompileRun("other.x;");
21512  CHECK(access_check_fail_thrown);
21513  CHECK(try_catch.HasCaught());
21514  }
21515 
21516  CheckCorrectThrow("other.x");
21517  CheckCorrectThrow("other[1]");
21518  CheckCorrectThrow("JSON.stringify(other)");
21519  CheckCorrectThrow("has_own_property(other, 'x')");
21520  CheckCorrectThrow("%GetProperty(other, 'x')");
21521  CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 1, 0)");
21522  CheckCorrectThrow("%IgnoreAttributesAndSetProperty(other, 'x', 'foo')");
21523  CheckCorrectThrow("%DeleteProperty(other, 'x', 0)");
21524  CheckCorrectThrow("%DeleteProperty(other, '1', 0)");
21525  CheckCorrectThrow("%HasLocalProperty(other, 'x')");
21526  CheckCorrectThrow("%HasProperty(other, 'x')");
21527  CheckCorrectThrow("%HasElement(other, 1)");
21528  CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
21529  CheckCorrectThrow("%GetPropertyNames(other)");
21530  // PROPERTY_ATTRIBUTES_NONE = 0
21531  CheckCorrectThrow("%GetLocalPropertyNames(other, 0)");
21532  CheckCorrectThrow("%DefineOrRedefineAccessorProperty("
21533  "other, 'x', null, null, 1)");
21534 
21535  // Reset the failed access check callback so it does not influence
21536  // the other tests.
21538 }
21539 
21540 
21541 THREADED_TEST(Regress256330) {
21542  i::FLAG_allow_natives_syntax = true;
21543  LocalContext context;
21544  v8::HandleScope scope(context->GetIsolate());
21545  Handle<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
21547  context->Global()->Set(v8_str("Bug"), templ->GetFunction());
21548  CompileRun("\"use strict\"; var o = new Bug;"
21549  "function f(o) { o.x = 10; };"
21550  "f(o); f(o); f(o);"
21551  "%OptimizeFunctionOnNextCall(f);"
21552  "f(o);");
21553  ExpectBoolean("%GetOptimizationStatus(f) != 2", true);
21554 }
21555 
21556 
21557 THREADED_TEST(CrankshaftInterceptorSetter) {
21558  i::FLAG_allow_natives_syntax = true;
21560  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21562  LocalContext env;
21563  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21564  CompileRun("var obj = new Obj;"
21565  // Initialize fields to avoid transitions later.
21566  "obj.age = 0;"
21567  "obj.accessor_age = 42;"
21568  "function setter(i) { this.accessor_age = i; };"
21569  "function getter() { return this.accessor_age; };"
21570  "function setAge(i) { obj.age = i; };"
21571  "Object.defineProperty(obj, 'age', { get:getter, set:setter });"
21572  "setAge(1);"
21573  "setAge(2);"
21574  "setAge(3);"
21575  "%OptimizeFunctionOnNextCall(setAge);"
21576  "setAge(4);");
21577  // All stores went through the interceptor.
21578  ExpectInt32("obj.interceptor_age", 4);
21579  ExpectInt32("obj.accessor_age", 42);
21580 }
21581 
21582 
21583 THREADED_TEST(CrankshaftInterceptorGetter) {
21584  i::FLAG_allow_natives_syntax = true;
21586  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21588  LocalContext env;
21589  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21590  CompileRun("var obj = new Obj;"
21591  // Initialize fields to avoid transitions later.
21592  "obj.age = 1;"
21593  "obj.accessor_age = 42;"
21594  "function getter() { return this.accessor_age; };"
21595  "function getAge() { return obj.interceptor_age; };"
21596  "Object.defineProperty(obj, 'interceptor_age', { get:getter });"
21597  "getAge();"
21598  "getAge();"
21599  "getAge();"
21600  "%OptimizeFunctionOnNextCall(getAge);");
21601  // Access through interceptor.
21602  ExpectInt32("getAge()", 1);
21603 }
21604 
21605 
21606 THREADED_TEST(CrankshaftInterceptorFieldRead) {
21607  i::FLAG_allow_natives_syntax = true;
21609  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21611  LocalContext env;
21612  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21613  CompileRun("var obj = new Obj;"
21614  "obj.__proto__.interceptor_age = 42;"
21615  "obj.age = 100;"
21616  "function getAge() { return obj.interceptor_age; };");
21617  ExpectInt32("getAge();", 100);
21618  ExpectInt32("getAge();", 100);
21619  ExpectInt32("getAge();", 100);
21620  CompileRun("%OptimizeFunctionOnNextCall(getAge);");
21621  // Access through interceptor.
21622  ExpectInt32("getAge();", 100);
21623 }
21624 
21625 
21626 THREADED_TEST(CrankshaftInterceptorFieldWrite) {
21627  i::FLAG_allow_natives_syntax = true;
21629  Handle<FunctionTemplate> templ = FunctionTemplate::New(CcTest::isolate());
21631  LocalContext env;
21632  env->Global()->Set(v8_str("Obj"), templ->GetFunction());
21633  CompileRun("var obj = new Obj;"
21634  "obj.age = 100000;"
21635  "function setAge(i) { obj.age = i };"
21636  "setAge(100);"
21637  "setAge(101);"
21638  "setAge(102);"
21639  "%OptimizeFunctionOnNextCall(setAge);"
21640  "setAge(103);");
21641  ExpectInt32("obj.age", 100000);
21642  ExpectInt32("obj.interceptor_age", 103);
21643 }
21644 
21645 
21647  public:
21649  : env_(),
21650  isolate_(env_->GetIsolate()),
21651  sem_(0),
21652  warmup_(20000),
21654  }
21655 
21657 
21658  virtual void TestBody() = 0;
21659 
21660  void RunTest() {
21661  InterruptThread i_thread(this);
21662  i_thread.Start();
21663 
21664  v8::HandleScope handle_scope(isolate_);
21665 
21666  TestBody();
21667 
21669 
21670  // Verify we arrived here because interruptor was called
21671  // not due to a bug causing us to exit the loop too early.
21672  CHECK(!should_continue());
21673  }
21674 
21676  sem_.Signal();
21677  }
21678 
21679  bool should_continue() const { return should_continue_; }
21680 
21682  if (warmup_ > 0) {
21683  if (--warmup_ == 0) {
21685  }
21686  }
21687 
21688  return should_continue_;
21689  }
21690 
21691  protected:
21693  const v8::FunctionCallbackInfo<Value>& info) {
21694  RequestInterruptTestBase* test =
21695  reinterpret_cast<RequestInterruptTestBase*>(
21696  info.Data().As<v8::External>()->Value());
21697  info.GetReturnValue().Set(test->ShouldContinue());
21698  }
21699 
21700  class InterruptThread : public i::Thread {
21701  public:
21703  : Thread("RequestInterruptTest"), test_(test) {}
21704 
21705  virtual void Run() {
21706  test_->sem_.Wait();
21707  test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
21708  }
21709 
21710  static void OnInterrupt(v8::Isolate* isolate, void* data) {
21711  reinterpret_cast<RequestInterruptTestBase*>(data)->
21712  should_continue_ = false;
21713  }
21714 
21715  private:
21716  RequestInterruptTestBase* test_;
21717  };
21718 
21721  i::Semaphore sem_;
21722  int warmup_;
21724 };
21725 
21726 
21728  public:
21729  virtual void TestBody() {
21730  Local<Function> func = Function::New(
21732  env_->Global()->Set(v8_str("ShouldContinue"), func);
21733 
21734  CompileRun("while (ShouldContinue()) { }");
21735  }
21736 };
21737 
21738 
21740  public:
21741  virtual void TestBody() {
21744  proto->Set(v8_str("shouldContinue"), Function::New(
21746  env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21747 
21748  CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21749  }
21750 };
21751 
21752 
21754  public:
21755  virtual void TestBody() {
21758  proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
21760  env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21761 
21762  CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21763  }
21764 };
21765 
21766 
21768  public:
21769  virtual void TestBody() {
21771  t->InstanceTemplate()->SetNativeDataProperty(
21772  v8_str("shouldContinue"),
21773  &ShouldContinueNativeGetter,
21774  NULL,
21775  v8::External::New(isolate_, this));
21776  env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21777 
21778  CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
21779  }
21780 
21781  private:
21782  static void ShouldContinueNativeGetter(
21783  Local<String> property,
21785  RequestInterruptTestBase* test =
21786  reinterpret_cast<RequestInterruptTestBase*>(
21787  info.Data().As<v8::External>()->Value());
21788  info.GetReturnValue().Set(test->ShouldContinue());
21789  }
21790 };
21791 
21792 
21794  : public RequestInterruptTestBase {
21795  public:
21796  virtual void TestBody() {
21799  proto->Set(v8_str("shouldContinue"), Function::New(
21801  v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
21802  instance_template->SetNamedPropertyHandler(EmptyInterceptor);
21803 
21804  env_->Global()->Set(v8_str("Klass"), t->GetFunction());
21805 
21806  CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
21807  }
21808 
21809  private:
21810  static void EmptyInterceptor(
21811  Local<String> property,
21813  }
21814 };
21815 
21816 
21818  public:
21819  virtual void TestBody() {
21820  env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
21821  isolate_,
21822  WakeUpInterruptorCallback,
21823  v8::External::New(isolate_, this)));
21824 
21825  env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
21826  isolate_,
21827  ShouldContinueCallback,
21828  v8::External::New(isolate_, this)));
21829 
21830  i::FLAG_allow_natives_syntax = true;
21831  CompileRun("function loopish(o) {"
21832  " var pre = 10;"
21833  " while (o.abs(1) > 0) {"
21834  " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
21835  " if (pre > 0) {"
21836  " if (--pre === 0) WakeUpInterruptor(o === Math);"
21837  " }"
21838  " }"
21839  "}"
21840  "var i = 50;"
21841  "var obj = {abs: function () { return i-- }, x: null};"
21842  "delete obj.x;"
21843  "loopish(obj);"
21844  "%OptimizeFunctionOnNextCall(loopish);"
21845  "loopish(Math);");
21846 
21847  i::FLAG_allow_natives_syntax = false;
21848  }
21849 
21850  private:
21851  static void WakeUpInterruptorCallback(
21852  const v8::FunctionCallbackInfo<Value>& info) {
21853  if (!info[0]->BooleanValue()) return;
21854 
21855  RequestInterruptTestBase* test =
21856  reinterpret_cast<RequestInterruptTestBase*>(
21857  info.Data().As<v8::External>()->Value());
21858  test->WakeUpInterruptor();
21859  }
21860 
21861  static void ShouldContinueCallback(
21862  const v8::FunctionCallbackInfo<Value>& info) {
21863  RequestInterruptTestBase* test =
21864  reinterpret_cast<RequestInterruptTestBase*>(
21865  info.Data().As<v8::External>()->Value());
21866  info.GetReturnValue().Set(test->should_continue());
21867  }
21868 };
21869 
21870 
21873 }
21874 
21875 
21878 }
21879 
21880 
21883 }
21884 
21885 
21888 }
21889 
21890 
21893 }
21894 
21895 
21898 }
21899 
21900 
21901 static Local<Value> function_new_expected_env;
21902 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
21903  CHECK_EQ(function_new_expected_env, info.Data());
21904  info.GetReturnValue().Set(17);
21905 }
21906 
21907 
21908 THREADED_TEST(FunctionNew) {
21909  LocalContext env;
21910  v8::Isolate* isolate = env->GetIsolate();
21911  v8::HandleScope scope(isolate);
21912  Local<Object> data = v8::Object::New(isolate);
21913  function_new_expected_env = data;
21914  Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
21915  env->Global()->Set(v8_str("func"), func);
21916  Local<Value> result = CompileRun("func();");
21917  CHECK_EQ(v8::Integer::New(isolate, 17), result);
21918  // Verify function not cached
21919  int serial_number =
21921  ->shared()->get_api_func_data()->serial_number())->value();
21922  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
21923  i::Handle<i::JSObject> cache(i_isolate->native_context()->function_cache());
21924  i::Handle<i::Object> elm =
21925  i::Object::GetElementNoExceptionThrown(i_isolate, cache, serial_number);
21926  CHECK(elm->IsUndefined());
21927  // Verify that each Function::New creates a new function instance
21928  Local<Object> data2 = v8::Object::New(isolate);
21929  function_new_expected_env = data2;
21930  Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
21931  CHECK(!func2->IsNull());
21932  CHECK_NE(func, func2);
21933  env->Global()->Set(v8_str("func2"), func2);
21934  Local<Value> result2 = CompileRun("func2();");
21935  CHECK_EQ(v8::Integer::New(isolate, 17), result2);
21936 }
21937 
21938 
21939 TEST(EscapeableHandleScope) {
21940  HandleScope outer_scope(CcTest::isolate());
21941  LocalContext context;
21942  const int runs = 10;
21943  Local<String> values[runs];
21944  for (int i = 0; i < runs; i++) {
21946  Local<String> value;
21947  if (i != 0) value = v8_str("escape value");
21948  values[i] = inner_scope.Escape(value);
21949  }
21950  for (int i = 0; i < runs; i++) {
21951  Local<String> expected;
21952  if (i != 0) {
21953  CHECK_EQ(v8_str("escape value"), values[i]);
21954  } else {
21955  CHECK(values[i].IsEmpty());
21956  }
21957  }
21958 }
21959 
21960 
21961 static void SetterWhichExpectsThisAndHolderToDiffer(
21962  Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
21963  CHECK(info.Holder() != info.This());
21964 }
21965 
21966 
21967 TEST(Regress239669) {
21968  LocalContext context;
21969  v8::Isolate* isolate = context->GetIsolate();
21970  v8::HandleScope scope(isolate);
21971  Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
21972  templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
21973  context->Global()->Set(v8_str("P"), templ->NewInstance());
21974  CompileRun(
21975  "function C1() {"
21976  " this.x = 23;"
21977  "};"
21978  "C1.prototype = P;"
21979  "for (var i = 0; i < 4; i++ ) {"
21980  " new C1();"
21981  "}");
21982 }
21983 
21984 
21986  private:
21987  static Local<Object> data;
21988  static Local<Object> receiver;
21989  static Local<Object> holder;
21990  static Local<Object> callee;
21991  static int count;
21992 
21993  static void OptimizationCallback(
21995  CHECK(callee == info.Callee());
21996  CHECK(data == info.Data());
21997  CHECK(receiver == info.This());
21998  if (info.Length() == 1) {
21999  CHECK_EQ(v8_num(1), info[0]);
22000  }
22001  CHECK(holder == info.Holder());
22002  count++;
22003  info.GetReturnValue().Set(v8_str("returned"));
22004  }
22005 
22006  public:
22011  };
22012 
22013  void RunAll() {
22014  SignatureType signature_types[] =
22016  for (unsigned i = 0; i < ARRAY_SIZE(signature_types); i++) {
22017  SignatureType signature_type = signature_types[i];
22018  for (int j = 0; j < 2; j++) {
22019  bool global = j == 0;
22020  int key = signature_type +
22021  ARRAY_SIZE(signature_types) * (global ? 1 : 0);
22022  Run(signature_type, global, key);
22023  }
22024  }
22025  }
22026 
22027  void Run(SignatureType signature_type, bool global, int key) {
22028  v8::Isolate* isolate = CcTest::isolate();
22029  v8::HandleScope scope(isolate);
22030  // Build a template for signature checks.
22031  Local<v8::ObjectTemplate> signature_template;
22032  Local<v8::Signature> signature;
22033  {
22034  Local<v8::FunctionTemplate> parent_template =
22035  FunctionTemplate::New(isolate);
22036  parent_template->SetHiddenPrototype(true);
22037  Local<v8::FunctionTemplate> function_template
22038  = FunctionTemplate::New(isolate);
22039  function_template->Inherit(parent_template);
22040  switch (signature_type) {
22041  case kNoSignature:
22042  break;
22043  case kSignatureOnReceiver:
22044  signature = v8::Signature::New(isolate, function_template);
22045  break;
22046  case kSignatureOnPrototype:
22047  signature = v8::Signature::New(isolate, parent_template);
22048  break;
22049  }
22050  signature_template = function_template->InstanceTemplate();
22051  }
22052  // Global object must pass checks.
22053  Local<v8::Context> context =
22054  v8::Context::New(isolate, NULL, signature_template);
22055  v8::Context::Scope context_scope(context);
22056  // Install regular object that can pass signature checks.
22057  Local<Object> function_receiver = signature_template->NewInstance();
22058  context->Global()->Set(v8_str("function_receiver"), function_receiver);
22059  // Get the holder objects.
22060  Local<Object> inner_global =
22061  Local<Object>::Cast(context->Global()->GetPrototype());
22062  // Install functions on hidden prototype object if there is one.
22063  data = Object::New(isolate);
22064  Local<FunctionTemplate> function_template = FunctionTemplate::New(
22065  isolate, OptimizationCallback, data, signature);
22066  Local<Function> function = function_template->GetFunction();
22067  Local<Object> global_holder = inner_global;
22068  Local<Object> function_holder = function_receiver;
22069  if (signature_type == kSignatureOnPrototype) {
22070  function_holder = Local<Object>::Cast(function_holder->GetPrototype());
22071  global_holder = Local<Object>::Cast(global_holder->GetPrototype());
22072  }
22073  global_holder->Set(v8_str("g_f"), function);
22074  global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
22075  function_holder->Set(v8_str("f"), function);
22076  function_holder->SetAccessorProperty(v8_str("acc"), function, function);
22077  // Initialize expected values.
22078  callee = function;
22079  count = 0;
22080  if (global) {
22081  receiver = context->Global();
22082  holder = inner_global;
22083  } else {
22084  holder = function_receiver;
22085  // If not using a signature, add something else to the prototype chain
22086  // to test the case that holder != receiver
22087  if (signature_type == kNoSignature) {
22088  receiver = Local<Object>::Cast(CompileRun(
22089  "var receiver_subclass = {};\n"
22090  "receiver_subclass.__proto__ = function_receiver;\n"
22091  "receiver_subclass"));
22092  } else {
22093  receiver = Local<Object>::Cast(CompileRun(
22094  "var receiver_subclass = function_receiver;\n"
22095  "receiver_subclass"));
22096  }
22097  }
22098  // With no signature, the holder is not set.
22099  if (signature_type == kNoSignature) holder = receiver;
22100  // build wrap_function
22101  i::ScopedVector<char> wrap_function(200);
22102  if (global) {
22104  wrap_function,
22105  "function wrap_f_%d() { var f = g_f; return f(); }\n"
22106  "function wrap_get_%d() { return this.g_acc; }\n"
22107  "function wrap_set_%d() { return this.g_acc = 1; }\n",
22108  key, key, key);
22109  } else {
22111  wrap_function,
22112  "function wrap_f_%d() { return receiver_subclass.f(); }\n"
22113  "function wrap_get_%d() { return receiver_subclass.acc; }\n"
22114  "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
22115  key, key, key);
22116  }
22117  // build source string
22118  i::ScopedVector<char> source(1000);
22120  source,
22121  "%s\n" // wrap functions
22122  "function wrap_f() { return wrap_f_%d(); }\n"
22123  "function wrap_get() { return wrap_get_%d(); }\n"
22124  "function wrap_set() { return wrap_set_%d(); }\n"
22125  "check = function(returned) {\n"
22126  " if (returned !== 'returned') { throw returned; }\n"
22127  "}\n"
22128  "\n"
22129  "check(wrap_f());\n"
22130  "check(wrap_f());\n"
22131  "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
22132  "check(wrap_f());\n"
22133  "\n"
22134  "check(wrap_get());\n"
22135  "check(wrap_get());\n"
22136  "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
22137  "check(wrap_get());\n"
22138  "\n"
22139  "check = function(returned) {\n"
22140  " if (returned !== 1) { throw returned; }\n"
22141  "}\n"
22142  "check(wrap_set());\n"
22143  "check(wrap_set());\n"
22144  "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
22145  "check(wrap_set());\n",
22146  wrap_function.start(), key, key, key, key, key, key);
22147  v8::TryCatch try_catch;
22148  CompileRun(source.start());
22149  ASSERT(!try_catch.HasCaught());
22150  CHECK_EQ(9, count);
22151  }
22152 };
22153 
22154 
22155 Local<Object> ApiCallOptimizationChecker::data;
22156 Local<Object> ApiCallOptimizationChecker::receiver;
22157 Local<Object> ApiCallOptimizationChecker::holder;
22158 Local<Object> ApiCallOptimizationChecker::callee;
22159 int ApiCallOptimizationChecker::count = 0;
22160 
22161 
22162 TEST(TestFunctionCallOptimization) {
22163  i::FLAG_allow_natives_syntax = true;
22165  checker.RunAll();
22166 }
22167 
22168 
22169 static const char* last_event_message;
22170 static int last_event_status;
22171 void StoringEventLoggerCallback(const char* message, int status) {
22172  last_event_message = message;
22173  last_event_status = status;
22174 }
22175 
22176 
22177 TEST(EventLogging) {
22178  v8::Isolate* isolate = CcTest::isolate();
22180  v8::internal::HistogramTimer* histogramTimer =
22182  "V8.Test", 0, 10000, 50,
22183  reinterpret_cast<v8::internal::Isolate*>(isolate));
22184  histogramTimer->Start();
22185  CHECK_EQ("V8.Test", last_event_message);
22186  CHECK_EQ(0, last_event_status);
22187  histogramTimer->Stop();
22188  CHECK_EQ("V8.Test", last_event_message);
22189  CHECK_EQ(1, last_event_status);
22190 }
22191 
22192 
22193 TEST(Promises) {
22194  LocalContext context;
22195  v8::Isolate* isolate = context->GetIsolate();
22196  v8::HandleScope scope(isolate);
22197  Handle<Object> global = context->Global();
22198 
22199  // Creation.
22200  Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
22201  Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
22202  Handle<v8::Promise> p = pr->GetPromise();
22203  Handle<v8::Promise> r = rr->GetPromise();
22204 
22205  // IsPromise predicate.
22206  CHECK(p->IsPromise());
22207  CHECK(r->IsPromise());
22208  Handle<Value> o = v8::Object::New(isolate);
22209  CHECK(!o->IsPromise());
22210 
22211  // Resolution and rejection.
22212  pr->Resolve(v8::Integer::New(isolate, 1));
22213  CHECK(p->IsPromise());
22214  rr->Reject(v8::Integer::New(isolate, 2));
22215  CHECK(r->IsPromise());
22216 
22217  // Chaining non-pending promises.
22218  CompileRun(
22219  "var x1 = 0;\n"
22220  "var x2 = 0;\n"
22221  "function f1(x) { x1 = x; return x+1 };\n"
22222  "function f2(x) { x2 = x; return x+1 };\n");
22223  Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
22224  Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
22225 
22226  p->Chain(f1);
22227  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22228  V8::RunMicrotasks(isolate);
22229  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
22230 
22231  p->Catch(f2);
22232  V8::RunMicrotasks(isolate);
22233  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22234 
22235  r->Catch(f2);
22236  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22237  V8::RunMicrotasks(isolate);
22238  CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
22239 
22240  r->Chain(f1);
22241  V8::RunMicrotasks(isolate);
22242  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
22243 
22244  // Chaining pending promises.
22245  CompileRun("x1 = x2 = 0;");
22246  pr = v8::Promise::Resolver::New(isolate);
22247  rr = v8::Promise::Resolver::New(isolate);
22248 
22249  pr->GetPromise()->Chain(f1);
22250  rr->GetPromise()->Catch(f2);
22251  V8::RunMicrotasks(isolate);
22252  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22253  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22254 
22255  pr->Resolve(v8::Integer::New(isolate, 1));
22256  rr->Reject(v8::Integer::New(isolate, 2));
22257  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22258  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22259 
22260  V8::RunMicrotasks(isolate);
22261  CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
22262  CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
22263 
22264  // Multi-chaining.
22265  CompileRun("x1 = x2 = 0;");
22266  pr = v8::Promise::Resolver::New(isolate);
22267  pr->GetPromise()->Chain(f1)->Chain(f2);
22268  pr->Resolve(v8::Integer::New(isolate, 3));
22269  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22270  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22271  V8::RunMicrotasks(isolate);
22272  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
22273  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
22274 
22275  CompileRun("x1 = x2 = 0;");
22276  rr = v8::Promise::Resolver::New(isolate);
22277  rr->GetPromise()->Catch(f1)->Chain(f2);
22278  rr->Reject(v8::Integer::New(isolate, 3));
22279  CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
22280  CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
22281  V8::RunMicrotasks(isolate);
22282  CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
22283  CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
22284 }
22285 
22286 
22287 TEST(DisallowJavascriptExecutionScope) {
22288  LocalContext context;
22289  v8::Isolate* isolate = context->GetIsolate();
22290  v8::HandleScope scope(isolate);
22293  CompileRun("2+2");
22294 }
22295 
22296 
22297 TEST(AllowJavascriptExecutionScope) {
22298  LocalContext context;
22299  v8::Isolate* isolate = context->GetIsolate();
22300  v8::HandleScope scope(isolate);
22306  CompileRun("1+1");
22307  }
22308 }
22309 
22310 
22312  LocalContext context;
22313  v8::Isolate* isolate = context->GetIsolate();
22314  v8::HandleScope scope(isolate);
22315  v8::TryCatch try_catch;
22318  CompileRun("1+1");
22319  CHECK(try_catch.HasCaught());
22320 }
22321 
22322 
22323 TEST(Regress354123) {
22324  LocalContext current;
22325  v8::Isolate* isolate = current->GetIsolate();
22326  v8::HandleScope scope(isolate);
22327 
22329  templ->SetAccessCheckCallbacks(NamedAccessCounter, IndexedAccessCounter);
22330  current->Global()->Set(v8_str("friend"), templ->NewInstance());
22331 
22332  // Test access using __proto__ from the prototype chain.
22333  named_access_count = 0;
22334  CompileRun("friend.__proto__ = {};");
22335  CHECK_EQ(2, named_access_count);
22336  CompileRun("friend.__proto__;");
22337  CHECK_EQ(4, named_access_count);
22338 
22339  // Test access using __proto__ as a hijacked function (A).
22340  named_access_count = 0;
22341  CompileRun("var p = Object.prototype;"
22342  "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
22343  "f.call(friend, {});");
22344  CHECK_EQ(1, named_access_count);
22345  CompileRun("var p = Object.prototype;"
22346  "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
22347  "f.call(friend);");
22348  CHECK_EQ(2, named_access_count);
22349 
22350  // Test access using __proto__ as a hijacked function (B).
22351  named_access_count = 0;
22352  CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
22353  "f.call(friend, {});");
22354  CHECK_EQ(1, named_access_count);
22355  CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
22356  "f.call(friend);");
22357  CHECK_EQ(2, named_access_count);
22358 
22359  // Test access using Object.setPrototypeOf reflective method.
22360  named_access_count = 0;
22361  CompileRun("Object.setPrototypeOf(friend, {});");
22362  CHECK_EQ(1, named_access_count);
22363  CompileRun("Object.getPrototypeOf(friend);");
22364  CHECK_EQ(2, named_access_count);
22365 }
v8::DefaultPersistentValueMapTraits< K, V >::Impl Impl
Definition: test-api.cc:3501
void Enter()
Definition: api.cc:650
static void RunAllTests()
Definition: test-api.cc:13173
byte * Address
Definition: globals.h:186
V8_INLINE UniquePersistent Pass()
Definition: v8.h:807
void DisposingCallback(const v8::WeakCallbackData< v8::Object, v8::Persistent< v8::Object > > &data)
Definition: test-api.cc:13566
void SetAccessor(Handle< String > name, AccessorGetterCallback getter, AccessorSetterCallback setter=0, Handle< Value > data=Handle< Value >(), AccessControl settings=DEFAULT, PropertyAttribute attribute=None, Handle< AccessorSignature > signature=Handle< AccessorSignature >())
Definition: api.cc:1404
v8::Handle< Value > keyed_call_ic_function
Definition: test-api.cc:12466
void RequestInterrupt(InterruptCallback callback, void *data)
Definition: api.cc:6554
static Local< Signature > New(Isolate *isolate, Handle< FunctionTemplate > receiver=Handle< FunctionTemplate >(), int argc=0, Handle< FunctionTemplate > argv[]=0)
Definition: api.cc:957
static Isolate * GetCurrent()
Definition: api.cc:6580
static Handle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype=true, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:12410
void ThrowFromC(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:4747
const SwVfpRegister s2
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static V8_INLINE Local< T > New(Isolate *isolate, Handle< T > that)
Definition: v8.h:5713
int prologue_call_count_alloc
Definition: test-api.cc:18589
int Length() const
Definition: api.cc:4137
static Local< Symbol > ForApi(Isolate *isolate, Local< String > name)
Definition: api.cc:6171
v8::Persistent< v8::Object > some_object
Definition: test-api.cc:13509
double NumberValue() const
Definition: api.cc:2829
static V8_INLINE Object * Cast(Value *obj)
Definition: v8.h:6359
void ThrowingDirectApiCallback(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:11974
static V8_INLINE Persistent< T > & Cast(Persistent< S > &that)
Definition: v8.h:705
int GetLineNumber() const
Definition: api.cc:2210
void FlattenString(Handle< String > string)
Definition: handles.cc:151
bool IsEval() const
Definition: api.cc:2288
void Fail(const v8::FunctionCallbackInfo< v8::Value > &args)
static void AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll)
Definition: api.cc:6469
V8_INLINE void SetWrapperClassId(uint16_t class_id)
Definition: v8.h:5896
bool HasRealIndexedProperty(uint32_t index)
Definition: api.cc:3499
void CheckCorrectThrow(const char *script)
Definition: test-api.cc:21456
virtual ~RequestInterruptTestBase()
Definition: test-api.cc:21656
TestAsciiResourceWithDisposeControl(const char *data, bool dispose)
Definition: test-api.cc:845
void set_max_young_space_size(int value)
Definition: v8.h:3951
virtual ~VisitorImpl()
Definition: test-api.cc:17777
Handle< String > NewExternalStringFromAscii(const ExternalAsciiString::Resource *resource)
Definition: factory.cc:554
#define CHECK_EQ(expected, value)
Definition: checks.h:252
bool IsTrue() const
Definition: api.cc:2347
SymbolMap symbols_
Definition: test-api.cc:13706
Local< Array > AsArray()
Definition: api.cc:2189
TEST(InitializeAndDisposeOnce)
Definition: test-api.cc:175
void RunWithProfiler(void(*test)())
Definition: test-api.cc:89
uint8_t * GetIndexedPropertiesPixelData()
Definition: api.cc:3774
v8::Handle< Value > call_ic_function
Definition: test-api.cc:11597
void CheckThisIndexedPropertySetter(uint32_t index, Local< Value > value, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:2298
CpuProfiler * GetCpuProfiler()
Definition: api.cc:6346
void StoringErrorCallback(const char *location, const char *message)
Definition: test-api.cc:7043
static int NumberOfHandles(Isolate *isolate)
Definition: api.cc:611
Local< Value > Call(Handle< Value > recv, int argc, Handle< Value > argv[])
Definition: api.cc:3996
void FastReturnValueCallback< uint32_t >(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1168
bool catch_callback_called
Definition: test-api.cc:21429
bool DeleteHiddenValue(Handle< String > key)
Definition: api.cc:3694
void Dispose()
Definition: api.cc:6592
void(* CallCompletedCallback)()
Definition: v8.h:4043
void SetEventLogger(LogEventCallback that)
Definition: api.cc:6676
void RunTest()
Definition: test-api.cc:13919
static void TearDown()
Definition: test-api.cc:13205
void EmptyInterceptorGetter(Local< String > name, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1931
static void Echo(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:6865
const Register r3
void Exit()
Definition: api.cc:6609
void CatcherCallback(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:21443
CompilationCache * compilation_cache()
Definition: isolate.h:867
Handle< FixedTypedArrayBase > NewFixedTypedArray(int length, ExternalArrayType array_type, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:762
Handle< String > InternalizeString(Handle< String > str)
Definition: factory.cc:225
void PrintF(const char *format,...)
Definition: v8utils.cc:40
void CollectAllGarbage(int flags, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap.cc:731
static Local< Private > ForApi(Isolate *isolate, Local< String > name)
Definition: api.cc:6201
static Local< Value > New(bool value)
Definition: api.cc:5620
Thread(const Options &options)
virtual void TestBody()=0
bool InNewSpace(Object *object)
Definition: heap-inl.h:307
void SetSecurityToken(Handle< Value > token)
Definition: api.cc:5207
Local< Value > Exception() const
Definition: api.cc:1923
void HandleCreatingCallback(const v8::WeakCallbackData< v8::Object, v8::Persistent< v8::Object > > &data)
Definition: test-api.cc:13571
static MapCache * cast(Object *obj)
void CallCompletedCallbackNoException()
Definition: test-api.cc:20555
void(* FunctionCallback)(const FunctionCallbackInfo< Value > &info)
Definition: v8.h:2603
~SetFunctionEntryHookTest()
Definition: test-api.cc:13660
void * user_data
Definition: v8.h:4549
bool StrictEquals(Handle< Value > that) const
Definition: api.cc:2977
V8_INLINE Isolate * GetIsolate() const
Definition: v8.h:6061
static void SetAddHistogramSampleFunction(AddHistogramSampleCallback)
Definition: api.cc:6319
Local< Value > Get(Handle< Value > key)
Definition: api.cc:3139
void AnalyzeStackOfInlineScriptWithSourceURL(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:17454
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
virtual void VisitPersistentHandle(Persistent< Value > *value, uint16_t class_id)
Definition: test-api.cc:19643
const int KB
Definition: globals.h:245
void SetObjectGroupId(const Persistent< T > &object, UniqueId id)
Definition: v8.h:6596
void V8_EXPORT RegisterExtension(Extension *extension)
Definition: api.cc:439
PropertyAttribute GetPropertyAttributes(Handle< Value > key)
Definition: api.cc:3171
Local< Object > NewInstance()
Definition: api.cc:5284
#define CHECK_GT(a, b)
Definition: checks.h:260
bool HasCaught() const
Definition: api.cc:1901
Local< Array > GetOwnPropertyNames()
Definition: api.cc:3259
V8_INLINE ReturnValue< T > GetReturnValue() const
Definition: v8.h:6067
v8::Persistent< v8::Object > to_be_disposed
Definition: test-api.cc:13541
int echo_named_call_count
Definition: test-api.cc:1904
bool SameValue(Handle< Value > that) const
Definition: api.cc:3009
void Reset()
Definition: test-api.cc:13664
void OnEntryHook(uintptr_t function, uintptr_t return_addr_location)
Definition: test-api.cc:13793
void HasOwnPropertyNamedPropertyQuery(Local< String > property, const v8::PropertyCallbackInfo< v8::Integer > &info)
Definition: test-api.cc:19982
bool IsBooleanObject() const
Definition: api.cc:2523
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
Local< String > Get() const
Definition: api.cc:1989
bool pass_on_get
Definition: test-api.cc:15245
void NewPersistentHandleCallback(const v8::WeakCallbackData< v8::Object, v8::Persistent< v8::Object > > &data)
Definition: test-api.cc:13512
static void SetCaptureStackTraceForUncaughtExceptions(bool capture, int frame_limit=10, StackTrace::StackTraceOptions options=StackTrace::kOverview)
Definition: api.cc:6294
void AllowCodeGenerationFromStrings(bool allow)
Definition: api.cc:5261
static v8::internal::Handle< v8::internal::Object > OpenPersistent(const v8::Persistent< T > &persistent)
Definition: api.h:295
Contents Externalize()
Definition: api.cc:5962
const Register r6
TickSample * sample
bool DeletePrivate(Handle< Private > key)
Definition: api.cc:3371
Definition: test-api.cc:13654
int epilogue_call_count
Definition: test-api.cc:18586
void * Data() const
Definition: test-api.cc:2956
void * new_code_start
Definition: v8.h:4576
UC16VectorResource(i::Vector< const i::uc16 > vector)
Definition: test-api.cc:15016
static ExternalTwoByteString * cast(Object *obj)
void checkStackFrame(const char *expected_script_name, const char *expected_func_name, int expected_line_number, int expected_column, bool is_eval, bool is_constructor, v8::Handle< v8::StackFrame > frame)
Definition: test-api.cc:17052
V8_INLINE void * GetAlignedPointerFromEmbedderData(int index)
Definition: v8.h:6637
V8_INLINE int Length() const
Definition: v8.h:6079
void FastReturnValueCallback(const v8::FunctionCallbackInfo< v8::Value > &info)
Local< ObjectTemplate > InstanceTemplate()
Definition: api.cc:1223
void OnJitEvent(const v8::JitCodeEvent *event)
Definition: test-api.cc:13750
double ValueOf() const
Definition: api.cc:5702
SetFunctionEntryHookTest()
Definition: test-api.cc:13656
kSerializedDataOffset Object
Definition: objects-inl.h:5016
bool IsSymbolObject() const
Definition: api.cc:2469
TestResource(uint16_t *data, int *counter=NULL, bool owning_data=true)
Definition: test-api.cc:464
ReturnValueOddball
Definition: test-api.cc:1146
bool ValueOf() const
Definition: api.cc:5634
Local< Value > ThrowException(Local< Value > exception)
Definition: api.cc:6386
int int32_t
Definition: unicode.cc:47
V8_INLINE Local< Function > Callee() const
Definition: v8.h:6035
static void DisableAutomaticDispose()
Definition: cctest.cc:105
void(* MessageCallback)(Handle< Message > message, Handle< Value > error)
Definition: v8.h:3987
void FastReturnValueCallback< int32_t >(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1161
static V8_INLINE uint32_t GetNumberOfDataSlots()
Definition: v8.h:6589
static v8::Local< v8::Object > global()
Definition: cctest.h:110
bool HasRealNamedCallbackProperty(Handle< String > key)
Definition: api.cc:3507
Local< Value > GetHiddenValue(Handle< String > key)
Definition: api.cc:3679
void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags)
Definition: test-api.cc:15175
V8_INLINE Local< Object > Holder() const
Definition: v8.h:6530
static void EnqueueMicrotask(Isolate *isolate, Handle< Function > microtask)
Definition: api.cc:6514
InvocationMap invocations_
Definition: test-api.cc:13708
size_t size
Definition: test-api.cc:13649
void CheckThisIndexedPropertyDeleter(uint32_t index, const v8::PropertyCallbackInfo< v8::Boolean > &info)
Definition: test-api.cc:2335
static Handle< Object > GetElementNoExceptionThrown(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: objects-inl.h:1071
static Local< Value > Error(Handle< String > message)
Definition: api.cc:6791
void FastReturnValueCallback< Object >(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1206
bool SetPrivate(Handle< Private > key, Handle< Value > value)
Definition: api.cc:3109
uintptr_t real_climit()
Definition: execution.h:241
V8_INLINE Local< T > Escape(Local< T > value)
Definition: v8.h:892
void AnalyzeStackOfEvalWithSourceURL(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:17371
Local< Array > GetPropertyNames()
Definition: api.cc:3238
ExternalArrayType GetIndexedPropertiesExternalArrayDataType()
Definition: api.cc:3844
void EpilogueCallbackAlloc(v8::Isolate *isolate, v8::GCType, v8::GCCallbackFlags flags)
Definition: test-api.cc:18672
#define CHECK_LT(a, b)
Definition: checks.h:262
THREADED_TEST(Handles)
Definition: test-api.cc:192
bool IsBuiltin() const
Definition: api.cc:4107
Local< Context > GetCurrentContext()
Definition: api.cc:6359
void AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll)
Definition: api.cc:6427
virtual void VisitExternalString(v8::Handle< v8::String > string)
Definition: test-api.cc:17778
void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags)
Definition: test-api.cc:18637
void FastReturnValueCallback< void >(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1189
V8_INLINE void Set(const Persistent< S > &handle)
#define ASSERT(condition)
Definition: checks.h:329
Local< Number > ToNumber() const
Definition: api.cc:2602
static i::Heap * heap()
Definition: cctest.h:106
static const int kReduceMemoryFootprintMask
Definition: heap.h:1259
ApiTestFuzzer * fuzzer_
Definition: cctest.h:231
Handle< Value > GetDisplayName() const
Definition: api.cc:4045
ExternalArrayType
Definition: v8.h:2113
unsigned short uint16_t
Definition: unicode.cc:46
void(* AccessorSetterCallback)(Local< String > property, Local< Value > value, const PropertyCallbackInfo< void > &info)
Definition: v8.h:2146
void * GetIndexedPropertiesExternalArrayData()
Definition: api.cc:3831
v8::Handle< Script > call_recursively_script
Definition: test-api.cc:2464
void TryCatchMixedNestingCheck(v8::TryCatch *try_catch)
Definition: test-api.cc:5294
std::map< std::pair< SymbolInfo *, SymbolInfo * >, int > InvocationMap
Definition: test-api.cc:13705
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition: api.cc:6233
V8_INLINE Local< Value > GetInternalField(int index)
Definition: v8.h:6139
void HasOwnPropertyAccessorGetter(Local< String > property, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:19996
static Local< Private > New(Isolate *isolate, Local< String > name=Local< String >())
Definition: api.cc:6189
Local< String > ToString() const
Definition: api.cc:2536
InterruptThread(RequestInterruptTestBase *test)
Definition: test-api.cc:21702
VisitorImpl(TestResource **resource)
Definition: test-api.cc:17771
#define CHECK(condition)
Definition: checks.h:75
void CThrowCountDown(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:5031
const Register r2
Local< Script > BindToCurrentContext()
Definition: api.cc:1627
#define THREADED_PROFILED_TEST(Name)
Definition: test-api.cc:81
static K KeyFromWeakCallbackData(const v8::WeakCallbackData< V, WeakCallbackDataType > &data)
Definition: test-api.cc:3518
static const int kNoScriptIdInfo
Definition: v8.h:1265
V8_INLINE bool IsConstructCall() const
Definition: v8.h:6073
void ThrowingDirectGetterCallback(Local< String > name, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:12045
void SetVerbose(bool value)
Definition: api.cc:1976
virtual size_t length() const
Definition: test-api.cc:15019
static Local< StackTrace > CurrentStackTrace(Isolate *isolate, int frame_limit, StackTraceOptions options=kOverview)
Definition: api.cc:2196
virtual const char * data() const
Definition: test-api.cc:15008
void Set(Handle< String > name, Handle< Data > value, PropertyAttribute attributes=None)
Definition: api.cc:841
void CheckThisIndexedPropertyEnumerator(const v8::PropertyCallbackInfo< v8::Array > &info)
Definition: test-api.cc:2353
Factory * factory()
Definition: isolate.h:995
static ExternalAsciiString * cast(Object *obj)
int prologue_call_count
Definition: test-api.cc:18585
UC16VectorResource * string_resource
Definition: test-api.cc:15149
#define CHECK_GE(a, b)
Definition: checks.h:261
size_t ByteOffset()
Definition: api.cc:6034
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
PropertyAttributes
Handle< Value > GetName() const
Definition: api.cc:4031
static V8_INLINE Symbol * Cast(v8::Value *obj)
Definition: v8.h:6287
static bool Dispose()
Definition: api.cc:5028
static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback)
Definition: api.cc:6325
void SetIndexedPropertiesToExternalArrayData(void *data, ExternalArrayType array_type, int number_of_elements)
Definition: api.cc:3799
void DirectApiCallback(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:11942
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
bool Equals(Handle< Value > that) const
Definition: api.cc:2950
void RemoveGCEpilogueCallback(GCEpilogueCallback callback)
Definition: api.cc:6447
void HasOwnPropertyCallback(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:21451
V8_INLINE P * ClearWeak()
static void VisitExternalResources(ExternalResourceVisitor *visitor)
Definition: api.cc:5047
static V8_INLINE Number * Cast(v8::Value *obj)
Definition: v8.h:6295
v8::Handle< Value > call_ic_function3
Definition: test-api.cc:11599
void RunLoopInNewEnv(v8::Isolate *isolate)
Definition: test-api.cc:13876
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
void CallCompletedCallbackException()
Definition: test-api.cc:20561
void HandleF(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:4394
Handle< Value > GetScriptResourceName() const
Definition: api.cc:2001
static void AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type_filter=kGCTypeAll)
Definition: api.cc:6453
static Smi * cast(Object *object)
Handle< String > FlattenGetString(Handle< String > string)
Definition: handles.cc:156
int GetId()
Definition: v8.h:1067
static void JitEvent(const v8::JitCodeEvent *event)
Definition: test-api.cc:13671
static V8_INLINE SymbolObject * Cast(v8::Value *obj)
Definition: v8.h:6327
bool IsExternal() const
Definition: api.cc:4769
bool HasIndexedPropertiesInExternalArrayData()
Definition: api.cc:3822
bool HasPrivate(Handle< Private > key)
Definition: api.cc:3390
v8::Isolate * GetIsolate()
Definition: api.cc:5233
bool Equals(String *other)
Definition: objects-inl.h:2969
static Local< UnboundScript > CompileUnbound(Isolate *isolate, Source *source, CompileOptions options=kNoCompileOptions)
Definition: api.cc:1723
v8::Persistent< Value > xValue
Definition: test-api.cc:5672
size_t id
Definition: test-api.cc:13648
void GetHeapStatistics(HeapStatistics *heap_statistics)
Definition: api.cc:6656
void SetNamedPropertyHandler(NamedPropertyGetterCallback getter, NamedPropertySetterCallback setter=0, NamedPropertyQueryCallback query=0, NamedPropertyDeleterCallback deleter=0, NamedPropertyEnumeratorCallback enumerator=0, Handle< Value > data=Handle< Value >())
Definition: api.cc:1416
void SetInternalField(int index, Handle< Value > value)
Definition: api.cc:4911
WeakCallCounterAndPersistent(WeakCallCounter *counter)
Definition: test-api.cc:3654
kInstanceClassNameOffset flag
Definition: objects-inl.h:5115
void SetClassName(Handle< String > name)
Definition: api.cc:1250
StackGuard * stack_guard()
Definition: isolate.h:874
int isnan(double x)
int foo
bool HasTerminated() const
Definition: api.cc:1911
void StartCpuProfiling(Handle< String > title, bool record_samples=false)
Definition: api.cc:7146
void CheckCodeGenerationAllowed()
Definition: test-api.cc:20099
void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags)
Definition: test-api.cc:18622
V8_INLINE Handle< Boolean > True(Isolate *isolate)
Definition: v8.h:6559
Local< StackFrame > GetFrame(uint32_t index) const
Definition: api.cc:2170
static const char * GetVersion()
Definition: api.cc:5120
static bool IsLocked(Isolate *isolate)
Definition: v8threads.cc:86
bool IsExternalAscii() const
Definition: api.cc:4776
static void TerminateExecution(Isolate *isolate=NULL)
Definition: api.cc:6531
void(* AccessorGetterCallback)(Local< String > property, const PropertyCallbackInfo< Value > &info)
Definition: v8.h:2141
RegExpInterruptionThread(v8::Isolate *isolate)
Definition: test-api.cc:15156
void CheckThisNamedPropertyQuery(Local< String > property, const v8::PropertyCallbackInfo< v8::Integer > &info)
Definition: test-api.cc:2326
bool IsStringObject() const
Definition: api.cc:2462
uint32_t ComputePointerHash(void *ptr)
Definition: utils.h:347
ScriptOrigin GetScriptOrigin() const
Definition: api.cc:4068
V8_INLINE bool IsNull() const
Definition: v8.h:6247
void SimpleAccessorGetter(Local< String > name, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1918
const SwVfpRegister s3
bool IsUint32() const
Definition: api.cc:2441
size_t length() const
Definition: test-api.cc:478
const int MB
Definition: d8.cc:174
bool access_check_fail_thrown
Definition: test-api.cc:21428
int InternalFieldCount()
Definition: api.cc:4887
#define UNREACHABLE()
Definition: checks.h:52
static bool AddMessageListener(MessageCallback that, Handle< Value > data=Handle< Value >())
Definition: api.cc:6259
size_t ByteLength()
Definition: api.cc:6040
const char * name()
Definition: cctest.h:232
void EnsureHeapIsIterable()
Definition: heap.cc:5679
void RemoveGCPrologueCallback(GCPrologueCallback callback)
Definition: api.cc:6434
virtual const char * Data()=0
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
void * Value() const
Definition: api.cc:5333
void CheckCodeGenerationDisallowed()
Definition: test-api.cc:20109
T * start() const
Definition: utils.h:426
static void RemoveCallCompletedCallback(CallCompletedCallback callback)
Definition: api.cc:6526
std::map< i::Address, SymbolInfo * > SymbolLocationMap
Definition: test-api.cc:13704
void set_max_old_space_size(int value)
Definition: v8.h:3953
V8_INLINE Local< Value > Data() const
Definition: v8.h:6055
void(* NamedPropertySetterCallback)(Local< String > property, Local< Value > value, const PropertyCallbackInfo< Value > &info)
Definition: v8.h:3312
void FooSetInterceptor(Local< String > name, Local< Value > value, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:18439
WeakCallCounter * counter
Definition: test-api.cc:3656
static Local< ObjectTemplate > New()
Definition: api.cc:1286
virtual bool HasError()=0
bool HasIndexedPropertiesInPixelData()
Definition: api.cc:3766
i::Handle< i::JSFunction > bar_func_
Definition: test-api.cc:13701
static void SetJitCodeEventHandler(JitCodeEventOptions options, JitCodeEventHandler event_handler)
Definition: api.cc:5010
void DetachGlobal()
Definition: api.cc:5253
bool IsSymbol() const
Definition: api.cc:2369
Handle< Value > ReThrow()
Definition: api.cc:1916
V8_INLINE Isolate * GetIsolate() const
Definition: v8.h:6512
static void MemCopy(void *dest, const void *src, size_t size)
Definition: platform.h:399
bool V8_EXPORT SetResourceConstraints(Isolate *isolate, ResourceConstraints *constraints)
Definition: api.cc:508
static void Fuzz()
Definition: test-api.cc:13100
void SimpleAccessorSetter(Local< String > name, Local< Value > value, const v8::PropertyCallbackInfo< void > &info)
Definition: test-api.cc:1925
Local< Value > GetPrototype()
Definition: api.cc:3192
virtual v8::Handle< v8::FunctionTemplate > GetNativeFunctionTemplate(v8::Isolate *isolate, v8::Handle< String > name)
Definition: test-api.cc:6988
v8::Isolate * isolate_
Definition: test-api.cc:21720
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1278
void set_resource(const Resource *buffer)
Definition: objects-inl.h:3258
void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags)
Definition: test-api.cc:18592
EventType type
Definition: v8.h:4538
v8::Isolate * gc_callbacks_isolate
Definition: test-api.cc:18584
void CollectAllAvailableGarbage(const char *gc_reason=NULL)
Definition: heap.cc:743
static const int kMinValue
Definition: objects.h:1679
bool ForceDelete(Handle< Value > key)
Definition: api.cc:3115
bool ToArrayIndex(uint32_t *index)
Definition: objects-inl.h:2072
v8::Handle< v8::Object > bottom
Definition: test-api.cc:2280
void CallCompletedCallback1()
Definition: test-api.cc:20492
byte * instruction_start()
Definition: objects-inl.h:5857
static const int kNoGCFlags
Definition: heap.h:1257
const Register r9
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:3313
V8_INLINE bool IsIndependent() const
Definition: v8.h:5779
int p_getter_count
Definition: test-api.cc:7407
void CheckProperties(v8::Isolate *isolate, v8::Handle< v8::Value > val, int elmc, const char *elmv[])
Definition: test-api.cc:14388
virtual ~AsciiVectorResource()
Definition: test-api.cc:15006
static Local< External > New(Isolate *isolate, void *value)
Definition: api.cc:5322
uint32_t occupancy() const
Definition: hashmap.h:83
V8_INLINE Local< Object > Holder() const
Definition: v8.h:6048
void JSCheck(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:5068
void SetInternalFieldCount(int value)
Definition: api.cc:1552
TestAsciiResource(const char *data, int *counter=NULL, size_t offset=0)
Definition: test-api.cc:492
int NumberOfWeakCalls()
Definition: test-api.cc:3645
int GetColumn() const
Definition: api.cc:2223
Local< Value > GetPrivate(Handle< Private > key)
Definition: api.cc:3166
static Isolate * New()
Definition: api.cc:6586
NativeFunctionExtension(const char *name, const char *source, v8::FunctionCallback fun=&Echo)
Definition: test-api.cc:6853
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
i::Handle< i::JSFunction > foo_func_
Definition: test-api.cc:13700
static void SetFatalErrorHandler(FatalErrorCallback that)
Definition: api.cc:393
static int ContextDisposedNotification()
Definition: api.cc:5108
bool CodeGenerationDisallowed(Local< Context > context)
Definition: test-api.cc:20134
void FastReturnValueCallback< double >(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1175
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=0, Handle< Value > data=Handle< Value >(), Handle< Signature > signature=Handle< Signature >(), int length=0)
Definition: api.cc:942
V8_INLINE void SetData(uint32_t slot, void *data)
Definition: v8.h:6577
int32_t Int32Value() const
Definition: api.cc:2929
static Local< Script > Compile(Handle< String > source, ScriptOrigin *origin=NULL, ScriptData *script_data=NULL)
Definition: api.cc:1832
void Version(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: shell.cc:211
bool IsBoolean() const
Definition: api.cc:2421
Local< Object > NewInstance() const
Definition: api.cc:3970
void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:17073
IsolateThread(v8::Isolate *isolate, int fib_limit)
Definition: test-api.cc:19311
PerIsolateAssertScope< JAVASCRIPT_EXECUTION_THROWS, false > ThrowOnJavascriptExecution
Definition: assert-scope.h:257
struct RegExpInterruptionData regexp_interruption_data
bool IsSharedCrossOrigin() const
Definition: api.cc:2130
int ScriptId() const
Definition: api.cc:4113
bool IsConstructor() const
Definition: api.cc:2298
static Local< Value > New(Isolate *isolate, Handle< Symbol > value)
Definition: api.cc:5664
Entry * Lookup(void *key, uint32_t hash, bool insert, AllocationPolicy allocator=AllocationPolicy())
Definition: hashmap.h:131
static V8_INLINE Handle< T > Cast(Handle< S > that)
Definition: v8.h:297
Local< Object > Global()
Definition: api.cc:5239
Handle< ExternalArray > NewExternalArray(int length, ExternalArrayType array_type, void *external_pointer, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:747
static FunctionTemplateInfo * cast(Object *obj)
void SetIndexedPropertiesToPixelData(uint8_t *data, int length)
Definition: api.cc:3745
static Local< ArrayBuffer > New(Isolate *isolate, size_t byte_length)
Definition: api.cc:5994
Handle< Value > TestFastReturnValues()
Definition: test-api.cc:1216
Handle< FixedArray > NewFixedArray(int size, PretenureFlag pretenure=NOT_TENURED)
Definition: factory.cc:53
void HasOwnPropertyIndexedPropertyQuery(uint32_t index, const v8::PropertyCallbackInfo< v8::Integer > &info)
Definition: test-api.cc:19976
void TurnOnAccessCheck()
Definition: api.cc:3588
bool InContext()
Definition: api.cc:6353
ScopedArrayBufferContents(const v8::ArrayBuffer::Contents &contents)
Definition: test-api.cc:2952
V8_INLINE ReturnValue< T > GetReturnValue() const
Definition: v8.h:6536
int prologue_call_count_second
Definition: test-api.cc:18587
int length() const
Definition: utils.h:420
struct name_t name
Definition: v8.h:4570
void TypedArrayTestHelper(v8::ExternalArrayType array_type, int64_t low, int64_t high)
Definition: test-api.cc:16873
void UnboxedDoubleIndexedPropertyEnumerator(const v8::PropertyCallbackInfo< v8::Array > &info)
Definition: test-api.cc:5935
int GetScriptColumnNumber() const
Definition: api.cc:4097
static i::Isolate * i_isolate()
Definition: cctest.h:102
void Enter()
Definition: api.cc:6603
static void RemoveMessageListeners(MessageCallback that)
Definition: api.cc:6275
GCType
Definition: v8.h:4067
const uint16_t * data() const
Definition: test-api.cc:474
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:4662
V8_INLINE Local< Object > This() const
Definition: v8.h:6042
v8::Persistent< v8::String > string
Definition: test-api.cc:15150
int CountInvocations(const char *caller_name, const char *function_name)
Definition: test-api.cc:13846
void increment()
Definition: test-api.cc:3644
void SloppyArgsIndexedPropertyEnumerator(const v8::PropertyCallbackInfo< v8::Array > &info)
Definition: test-api.cc:5974
bool SetHiddenValue(Handle< String > key, Handle< Value > value)
Definition: api.cc:3661
void CheckThisNamedPropertyEnumerator(const v8::PropertyCallbackInfo< v8::Array > &info)
Definition: test-api.cc:2361
void set_stack_limit(uint32_t *value)
Definition: v8.h:3958
OldSpace * code_space()
Definition: heap.h:640
const SwVfpRegister s0
static const int kMakeHeapIterableMask
Definition: heap.h:1264
void SetAlignedPointerInEmbedderData(int index, void *value)
Definition: api.cc:740
uint8_t callback_fired
Definition: test-api.cc:20489
AccessType
Definition: v8.h:3395
Local< Symbol > ValueOf() const
Definition: api.cc:5675
void HasOwnPropertyNamedPropertyQuery2(Local< String > property, const v8::PropertyCallbackInfo< v8::Integer > &info)
Definition: test-api.cc:19989
static V8_INLINE String * Cast(v8::Value *obj)
Definition: v8.h:6174
virtual void Run()
Definition: test-api.cc:13128
void * Data() const
Definition: v8.h:2780
void FailedAccessCheckCallbackGC(Local< v8::Object > target, v8::AccessType type, Local< v8::Value > data)
Definition: test-api.cc:19047
Definition: v8.h:123
bool BooleanValue() const
Definition: api.cc:2824
static V8_INLINE External * Cast(Value *obj)
Definition: v8.h:6503
virtual v8::Handle< v8::FunctionTemplate > GetNativeFunctionTemplate(v8::Isolate *isolate, v8::Handle< v8::String > name)
Definition: test-api.cc:6859
static Local< Number > New(Isolate *isolate, double value)
Definition: api.cc:6220
void FailedAccessCheckThrows(Local< v8::Object > target, v8::AccessType type, Local< v8::Value > data)
Definition: test-api.cc:21433
void set_resource(const Resource *buffer)
Definition: objects-inl.h:3291
const FPURegister f2
static Local< String > NewFromTwoByte(Isolate *isolate, const uint16_t *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5443
size_t length() const
Definition: test-api.cc:507
bool SetPrototype(Handle< Value > prototype)
Definition: api.cc:3203
void CheckThisNamedPropertyDeleter(Local< String > property, const v8::PropertyCallbackInfo< v8::Boolean > &info)
Definition: test-api.cc:2344
static Local< Array > New(Isolate *isolate, int length=0)
Definition: api.cc:5786
V8_INLINE bool IsUndefined() const
Definition: v8.h:6229
int GetLineNumber() const
Definition: api.cc:2061
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:308
V8_INLINE Handle< Primitive > Undefined(Isolate *isolate)
Definition: v8.h:6541
static Local< Value > RangeError(Handle< String > message)
Definition: api.cc:6722
#define CHECK_NE(unexpected, value)
Definition: checks.h:256
static V8_INLINE Local< Object > Cast(Local< S > that)
Definition: v8.h:372
void SetHiddenPrototype(bool value)
Definition: api.cc:1257
V8_INLINE uint16_t WrapperClassId() const
Definition: v8.h:5906
static void Sleep(const int milliseconds)
static const int kAbortIncrementalMarkingMask
Definition: heap.h:1260
Vector< const char > CStrVector(const char *data)
Definition: utils.h:574
bool CollectGarbage(AllocationSpace space, const char *gc_reason=NULL, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition: heap-inl.h:554
V8_INLINE P * GetParameter() const
Definition: v8.h:451
int StrLength(const char *string)
Definition: utils.h:253
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
#define CHECK_LE(a, b)
Definition: checks.h:263
static Local< Object > New(Isolate *isolate)
Definition: api.cc:5589
static void Print(const char *format,...)
intptr_t SizeOfObjects()
Definition: heap.cc:473
void DisposeAndForceGcCallback(const v8::WeakCallbackData< v8::Object, v8::Persistent< v8::Object > > &data)
Definition: test-api.cc:13543
#define T(name, string, precedence)
Definition: token.cc:48
static void AddCallCompletedCallback(CallCompletedCallback callback)
Definition: api.cc:6501
void HasOwnPropertyIndexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:19962
Definition: v8.h:2472
Local< String > GetScriptName() const
Definition: api.cc:2249
static bool SetFunctionEntryHook(Isolate *isolate, FunctionEntryHook entry_hook)
Definition: api.cc:4987
void FastReturnValueCallback< bool >(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1182
Context * context()
Definition: isolate.h:557
V8_INLINE bool IsString() const
Definition: v8.h:6265
static Local< Value > New(Isolate *isolate, double value)
Definition: api.cc:5600
const SwVfpRegister s1
size_t ByteLength() const
Definition: v8.h:2781
std::map< size_t, SymbolInfo > SymbolMap
Definition: test-api.cc:13703
bool IsObject() const
Definition: api.cc:2411
static Local< Value > New(Isolate *isolate, double time)
Definition: api.cc:5685
void Run(SignatureType signature_type, bool global, int key)
Definition: test-api.cc:22027
Definition: v8.h:2107
void ExtArrayLimitsHelper(v8::Isolate *isolate, v8::ExternalArrayType array_type, int size)
Definition: test-api.cc:16833
void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags)
Definition: test-api.cc:18607
double Value() const
Definition: api.cc:4845
bool IsCodeGenerationFromStringsAllowed()
Definition: api.cc:5270
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:5188
static Local< Value > ReferenceError(Handle< String > message)
Definition: api.cc:6739
void FooGetInterceptor(Local< String > name, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:18430
void SetReferenceFromGroup(UniqueId id, const Persistent< T > &child)
Definition: v8.h:6604
virtual ~UC16VectorResource()
Definition: test-api.cc:15018
static int SNPrintF(Vector< char > str, const char *format,...)
Local< Value > StackTrace() const
Definition: api.cc:1935
size_t Length()
Definition: api.cc:6046
PlatformData * data()
Definition: platform.h:605
static Local< DataView > New(Handle< ArrayBuffer > array_buffer, size_t byte_offset, size_t length)
Definition: api.cc:6127
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array shift
void GetThisX(const v8::FunctionCallbackInfo< v8::Value > &info)
Definition: test-api.cc:8748
void CheckThisIndexedPropertyQuery(uint32_t index, const v8::PropertyCallbackInfo< v8::Integer > &info)
Definition: test-api.cc:2317
static void RuntimeCallback(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:13684
static Local< RegExp > New(Handle< String > pattern, Flags flags)
Definition: api.cc:5748
int ToNumber(Register reg)
V8_INLINE Handle< Boolean > False(Isolate *isolate)
Definition: v8.h:6568
v8::Persistent< T > handle
Definition: test-api.cc:3657
static void WriteToFlat(String *source, sinkchar *sink, int from, int to)
Definition: objects.cc:8635
int GetIndexedPropertiesExternalArrayDataLength()
Definition: api.cc:3861
const Register r1
void CCatcher(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:4753
uint32_t Uint32Value() const
Definition: api.cc:3023
static double nan_value()
V8_INLINE Local< S > As()
Definition: v8.h:385
v8::Persistent< v8::Object > handle
Definition: test-api.cc:7089
void SetReference(const Persistent< T > &parent, const Persistent< S > &child)
Definition: v8.h:6613
void Exit()
Definition: api.cc:661
bool is_null() const
Definition: handles.h:81
V8_INLINE Local< Object > This() const
Definition: v8.h:6524
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
void Neuter()
Definition: api.cc:5976
V8_INLINE bool IsEmpty() const
Definition: v8.h:248
bool IsNumber() const
Definition: api.cc:2416
void RecursiveCall(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:20504
void CallCompletedCallback2()
Definition: test-api.cc:20498
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
#define IS_ARRAY_BUFFER_VIEW_TEST(View)
Definition: test-api.cc:16982
Local< Function > GetFunction()
Definition: api.cc:5299
void CheckVisitedResources()
Definition: test-api.cc:17793
static RegisterThreadedTest * nth(int i)
Definition: cctest.h:221
StrongMapTraits< K, V >::Impl Impl
Definition: v8-util.h:124
uint16_t uc16
Definition: globals.h:309
bool ForceSet(Handle< Value > key, Handle< Value > value, PropertyAttribute attribs=None)
Definition: api.cc:3087
int GetUtf8Length(Handle< String > str)
Definition: test-api.cc:7531
void InsertSymbolAt(i::Address addr, SymbolInfo *symbol)
Definition: test-api.cc:13723
V8_INLINE bool IsEmpty() const
Definition: v8.h:497
static Local< Value > SyntaxError(Handle< String > message)
Definition: api.cc:6757
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
void(* NamedPropertyGetterCallback)(Local< String > property, const PropertyCallbackInfo< Value > &info)
Definition: v8.h:3303
static Local< String > NewExternal(Isolate *isolate, ExternalStringResource *resource)
Definition: api.cc:5493
Local< Object > Clone()
Definition: api.cc:3611
virtual int Length()=0
void AnalyzeStackOfDynamicScriptWithSourceURL(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:17500
Local< Value > GetBoundFunction() const
Definition: api.cc:4123
v8::Persistent< v8::Object > bad_handle
Definition: test-api.cc:13510
static SetFunctionEntryHookTest * instance_
Definition: test-api.cc:13710
V8_INLINE void Reset()
Definition: v8.h:5808
const Register r8
void ClearInterrupt()
Definition: api.cc:6560
virtual const i::uc16 * data() const
Definition: test-api.cc:15020
static const bool kIsWeak
Definition: test-api.cc:3502
V8_INLINE void * GetData(uint32_t slot)
Definition: v8.h:6583
void * Remove(void *key, uint32_t hash)
Definition: hashmap.h:162
Local< Value > Name() const
Definition: api.cc:4840
AsciiVectorResource(i::Vector< const char > vector)
Definition: test-api.cc:15004
const char * data() const
Definition: test-api.cc:503
int GetIndexedPropertiesPixelDataLength()
Definition: api.cc:3787
WeakCallCounter(int id)
Definition: test-api.cc:3642
Local< ObjectTemplate > PrototypeTemplate()
Definition: api.cc:888
static void VisitHandlesWithClassIds(PersistentHandleVisitor *visitor)
Definition: api.cc:5070
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
const FPURegister f1
int counter_
Definition: test-api.cc:19657
SymbolInfo * FindSymbolForAddr(i::Address addr)
Definition: test-api.cc:13825
static Local< Value > TypeError(Handle< String > message)
Definition: api.cc:6774
double ValueOf() const
Definition: api.cc:5611
Definition: v8.h:3069
V8_INLINE Isolate * GetIsolate()
Definition: v8.h:6004
void USE(T)
Definition: globals.h:341
const SwVfpRegister s4
void WithTryCatch(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:5246
int GetScriptLineNumber() const
Definition: api.cc:4087
static Local< Resolver > New(Isolate *isolate)
Definition: api.cc:5855
virtual size_t length() const
Definition: test-api.cc:15007
static void RemoveGCEpilogueCallback(GCEpilogueCallback callback)
Definition: api.cc:6478
Handle< StackTrace > GetStackTrace() const
Definition: api.cc:2017
InitDefaultIsolateThread(TestCase testCase)
Definition: test-api.cc:19393
static void VisitHandlesForPartialDependence(Isolate *isolate, PersistentHandleVisitor *visitor)
Definition: api.cc:5079
static void SetCreateHistogramFunction(CreateHistogramCallback)
Definition: api.cc:6311
bool IsNumberObject() const
Definition: api.cc:2478
static void RemoveGCPrologueCallback(GCPrologueCallback callback)
Definition: api.cc:6462
void UnreachableCallback(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:21373
void StoringEventLoggerCallback(const char *message, int status)
Definition: test-api.cc:22171
void * GetData(uint32_t slot)
Definition: isolate.h:1007
void CheckThisNamedPropertySetter(Local< String > property, Local< Value > value, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:2308
static void ShouldContinueCallback(const v8::FunctionCallbackInfo< Value > &info)
Definition: test-api.cc:21692
static void Dispose(v8::Isolate *isolate, v8::UniquePersistent< V > value, Impl *impl, K key)
Definition: test-api.cc:3525
void(* NamedPropertyGetter)(Local< String > property, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:11131
Local< Value > Run()
Definition: api.cc:1686
void PrologueCallbackAlloc(v8::Isolate *isolate, v8::GCType, v8::GCCallbackFlags flags)
Definition: test-api.cc:18652
bool Has(Handle< Value > key)
Definition: api.cc:3376
void AnalyzeScriptIdInStack(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:17419
int echo_indexed_call_count
Definition: test-api.cc:2252
bool IsOneByteRepresentation()
Definition: objects-inl.h:321
bool CodeGenerationAllowed(Local< Context > context)
Definition: test-api.cc:20128
void InterceptorGetter(Local< String > name, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1940
void ClearJSFunctionResultCaches()
Definition: heap.cc:995
void AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type_filter=kGCTypeAll)
Definition: api.cc:6440
GCCallbackFlags
Definition: v8.h:4073
static Handle< Object > GetElement(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: objects-inl.h:1060
UNINITIALIZED_TEST(SetJitCodeEventHandler)
Definition: test-api.cc:14125
const Register r10
void AddInterceptor(Handle< FunctionTemplate > templ, v8::NamedPropertyGetterCallback getter, v8::NamedPropertySetterCallback setter)
Definition: test-api.cc:1982
static Local< Value > Parse(Local< String > json_string)
Definition: api.cc:2310
CcTest::TestFunction * callback()
Definition: cctest.h:230
static Local< TypeSwitch > New(Handle< FunctionTemplate > type)
Definition: api.cc:1104
bool IsArray() const
Definition: api.cc:2374
int64_t AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes)
Definition: api.cc:6332
HeapObject * obj
void CallTest()
Definition: test-api.cc:13243
void SetAccessorProperty(Local< String > name, Local< FunctionTemplate > getter=Local< FunctionTemplate >(), Local< FunctionTemplate > setter=Local< FunctionTemplate >(), PropertyAttribute attribute=None, AccessControl settings=DEFAULT)
Definition: api.cc:857
int epilogue_call_count_second
Definition: test-api.cc:18588
void EmptyInterceptorSetter(Local< String > name, Local< Value > value, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1935
void TryCatchMixedNestingHelper(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:5306
char * StrDup(const char *str)
Definition: allocation.cc:89
uint32_t Length() const
Definition: api.cc:5800
bool message_received
Definition: test-api.cc:4105
Local< Value > Name() const
Definition: api.cc:4833
static Local< AccessorSignature > New(Isolate *isolate, Handle< FunctionTemplate > receiver=Handle< FunctionTemplate >())
Definition: api.cc:981
Handle< Context > native_context()
Definition: isolate.cc:1372
static ScriptData * New(const char *data, int length)
Definition: api.cc:1587
size_t ByteLength() const
Definition: test-api.cc:2957
Local< Boolean > ToBoolean() const
Definition: api.cc:2587
static Local< Symbol > New(Isolate *isolate, Local< String > name=Local< String >())
Definition: api.cc:6142
void SetIndexedPropertyHandler(IndexedPropertyGetterCallback getter, IndexedPropertySetterCallback setter=0, IndexedPropertyQueryCallback query=0, IndexedPropertyDeleterCallback deleter=0, IndexedPropertyEnumeratorCallback enumerator=0, Handle< Value > data=Handle< Value >())
Definition: api.cc:1492
size_t ByteLength() const
Definition: api.cc:5988
V8_INLINE Handle< S > As()
Definition: v8.h:306
void AddAccessor(Handle< FunctionTemplate > templ, Handle< String > name, v8::AccessorGetterCallback getter, v8::AccessorSetterCallback setter)
Definition: test-api.cc:1975
bool IsInt32() const
Definition: api.cc:2431
v8::Local< v8::Context > local()
Definition: cctest.h:272
int bar
bool HasRealNamedProperty(Handle< String > key)
Definition: api.cc:3490
std::map< K, PersistentContainerValue > Impl
Definition: v8-util.h:57
static WeakCallbackDataType * WeakCallbackParameter(Impl *impl, const K &key, Local< V > value)
Definition: test-api.cc:3507
void InterceptorSetter(Local< String > name, Local< Value > value, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:1954
static ScriptData * PreCompile(Handle< String > source)
Definition: api.cc:1573
bool Delete(Handle< Value > key)
Definition: api.cc:3356
static void SetUp(PartOfTest part)
Definition: test-api.cc:13152
int p_getter_count2
Definition: test-api.cc:7408
void DeleteArray(T *array)
Definition: allocation.h:91
Handle< Value > GetInferredName() const
Definition: api.cc:4038
void ExternalArrayInfoTestHelper(v8::ExternalArrayType array_type)
Definition: test-api.cc:16802
void CheckOwnProperties(v8::Isolate *isolate, v8::Handle< v8::Value > val, int elmc, const char *elmv[])
Definition: test-api.cc:14402
static ConsString * cast(Object *obj)
#define FUNCTION_ADDR(f)
Definition: globals.h:345
V8_INLINE void SetWeak(P *parameter, typename WeakCallbackData< T, P >::Callback callback)
bool SetAccessor(Handle< String > name, AccessorGetterCallback getter, AccessorSetterCallback setter=0, Handle< Value > data=Handle< Value >(), AccessControl settings=DEFAULT, PropertyAttribute attribute=None)
Definition: api.cc:3439
static void EntryHook(uintptr_t function, uintptr_t return_addr_location)
Definition: test-api.cc:13678
SymbolLocationMap symbol_locations_
Definition: test-api.cc:13707
v8::Persistent< v8::Object > * object_
Definition: test-api.cc:19658
V8_INLINE Local< Value > Data() const
Definition: v8.h:6518
static const int kMaxValue
Definition: objects.h:1681
void * code_start
Definition: v8.h:4540
void Reset()
Definition: api.cc:1965
V8_INLINE void MarkIndependent()
Definition: v8.h:5867
const char * str
Definition: v8.h:4554
v8::Handle< Function > args_fun
Definition: test-api.cc:7225
#define ARRAY_SIZE(a)
Definition: globals.h:333
void SetErrorMessageForCodeGenerationFromStrings(Handle< String > message)
Definition: api.cc:5276
static Local< Value > New(Handle< String > value)
Definition: api.cc:5643
Local< String > ValueOf() const
Definition: api.cc:5654
static V8_INLINE v8::Local< v8::String > Empty(Isolate *isolate)
Definition: v8.h:6182
int match(Handle< Value > value)
Definition: api.cc:1127
Local< v8::Message > Message() const
Definition: api.cc:1953
V8_INLINE Handle< Primitive > Null(Isolate *isolate)
Definition: v8.h:6550
static Impl * ImplFromWeakCallbackData(const v8::WeakCallbackData< V, WeakCallbackDataType > &data)
Definition: test-api.cc:3514
std::string name
Definition: test-api.cc:13650
AccessControl
Definition: v8.h:2165
void Inherit(Handle< FunctionTemplate > parent)
Definition: api.cc:902
void ThrowValue(const v8::FunctionCallbackInfo< v8::Value > &args)
Definition: test-api.cc:5175
static bool Initialize()
Definition: api.cc:4967
Visitor42(v8::Persistent< v8::Object > *object)
Definition: test-api.cc:19640
int epilogue_call_count_alloc
Definition: test-api.cc:18590
Local< String > GetFunctionName() const
Definition: api.cc:2275
Local< String > GetSourceLine() const
Definition: api.cc:2143
size_t code_len
Definition: v8.h:4542
const Register r5
static void SetCounterFunction(CounterLookupCallback)
Definition: api.cc:6305
Local< Uint32 > ToArrayIndex() const
Definition: api.cc:2901
void HasOwnPropertyNamedPropertyGetter(Local< String > property, const v8::PropertyCallbackInfo< v8::Value > &info)
Definition: test-api.cc:19969
static V8_INLINE Handle< Boolean > New(Isolate *isolate, bool value)
Definition: v8.h:6129
int GetIdentityHash()
Definition: api.cc:3650
bool should_continue() const
Definition: test-api.cc:21679
static int count()
Definition: cctest.h:220
void SetAccessCheckCallbacks(NamedSecurityCallback named_handler, IndexedSecurityCallback indexed_handler, Handle< Value > data=Handle< Value >(), bool turned_on_by_default=true)
Definition: api.cc:1461
static void DisposeCallbackData(WeakCallbackDataType *data)
Definition: test-api.cc:3522
bool Value() const
Definition: api.cc:4851
static Local< Integer > NewFromUnsigned(Isolate *isolate, uint32_t value)
Definition: api.cc:6246
bool Set(Handle< Value > key, Handle< Value > value, PropertyAttribute attribs=None)
Definition: api.cc:3044
static v8::Isolate * isolate()
Definition: cctest.h:96
const char * name() const
Definition: platform.h:561
int GetFrameCount() const
Definition: api.cc:2182
static void OnInterrupt(v8::Isolate *isolate, void *data)
Definition: test-api.cc:21710
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
Definition: api.cc:5417
const Register r4
static bool IdleNotification(int hint=1000)
Definition: api.cc:5091
v8::Handle< Value > call_ic_function2
Definition: test-api.cc:11598
static Local< Symbol > For(Isolate *isolate, Local< String > name)
Definition: api.cc:6153
const Register r7