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
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.
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.
33 #include "test/cctest/test-api.h"
36 #include <unistd.h> // NOLINT
39 #include "include/v8-util.h"
41 #include "src/arguments.h"
42 #include "src/base/platform/platform.h"
43 #include "src/base/smart-pointers.h"
44 #include "src/compilation-cache.h"
45 #include "src/debug/debug.h"
46 #include "src/execution.h"
47 #include "src/futex-emulation.h"
48 #include "src/objects.h"
49 #include "src/parser.h"
50 #include "src/unicode-inl.h"
51 #include "src/utils.h"
52 #include "src/vm-state.h"
54 static const bool kLogThreading = false;
57 using ::v8::BooleanObject;
59 using ::v8::Extension;
61 using ::v8::FunctionTemplate;
63 using ::v8::HandleScope;
67 using ::v8::MessageCallback;
71 using ::v8::ObjectTemplate;
72 using ::v8::Persistent;
73 using ::v8::PropertyAttribute;
75 using ::v8::StackTrace;
79 using ::v8::Undefined;
85 #define THREADED_PROFILED_TEST(Name) \
86 static void Test##Name(); \
87 TEST(Name##WithProfiler) { \
88 RunWithProfiler(&Test##Name); \
93 void RunWithProfiler(void (*test)()) {
95 v8::HandleScope scope(env->GetIsolate());
96 v8::Local<v8::String> profile_name =
97 v8::String::NewFromUtf8(env->GetIsolate(), "my_profile1");
98 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
100 cpu_profiler->StartProfiling(profile_name);
102 reinterpret_cast<i::CpuProfiler*>(cpu_profiler)->DeleteAllProfiles();
106 static int signature_callback_count;
107 static Local<Value> signature_expected_receiver;
108 static void IncrementingSignatureCallback(
109 const v8::FunctionCallbackInfo<v8::Value>& args) {
110 ApiTestFuzzer::Fuzz();
111 signature_callback_count++;
112 CHECK(signature_expected_receiver->Equals(args.Holder()));
113 CHECK(signature_expected_receiver->Equals(args.This()));
114 v8::Handle<v8::Array> result =
115 v8::Array::New(args.GetIsolate(), args.Length());
116 for (int i = 0; i < args.Length(); i++)
117 result->Set(v8::Integer::New(args.GetIsolate(), i), args[i]);
118 args.GetReturnValue().Set(result);
122 static void Returns42(const v8::FunctionCallbackInfo<v8::Value>& info) {
123 info.GetReturnValue().Set(42);
127 // Tests that call v8::V8::Dispose() cannot be threaded.
128 UNINITIALIZED_TEST(InitializeAndDisposeOnce) {
129 CHECK(v8::V8::Initialize());
130 CHECK(v8::V8::Dispose());
134 // Tests that call v8::V8::Dispose() cannot be threaded.
135 UNINITIALIZED_TEST(InitializeAndDisposeMultiple) {
136 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
137 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
138 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
139 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Initialize());
140 for (int i = 0; i < 3; ++i) CHECK(v8::V8::Dispose());
144 THREADED_TEST(Handles) {
145 v8::HandleScope scope(CcTest::isolate());
146 Local<Context> local_env;
149 local_env = env.local();
152 // Local context should still be live.
153 CHECK(!local_env.IsEmpty());
156 v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
157 CHECK(!undef.IsEmpty());
158 CHECK(undef->IsUndefined());
160 const char* source = "1 + 2 + 3";
161 Local<Script> script = v8_compile(source);
162 CHECK_EQ(6, script->Run()->Int32Value());
168 THREADED_TEST(IsolateOfContext) {
169 v8::HandleScope scope(CcTest::isolate());
170 v8::Handle<Context> env = Context::New(CcTest::isolate());
172 CHECK(!env->GetIsolate()->InContext());
173 CHECK(env->GetIsolate() == CcTest::isolate());
175 CHECK(env->GetIsolate()->InContext());
176 CHECK(env->GetIsolate() == CcTest::isolate());
178 CHECK(!env->GetIsolate()->InContext());
179 CHECK(env->GetIsolate() == CcTest::isolate());
183 static void TestSignature(const char* loop_js, Local<Value> receiver,
184 v8::Isolate* isolate) {
185 i::ScopedVector<char> source(200);
187 "for (var i = 0; i < 10; i++) {"
191 signature_callback_count = 0;
192 signature_expected_receiver = receiver;
193 bool expected_to_throw = receiver.IsEmpty();
194 v8::TryCatch try_catch(isolate);
195 CompileRun(source.start());
196 CHECK_EQ(expected_to_throw, try_catch.HasCaught());
197 if (!expected_to_throw) {
198 CHECK_EQ(10, signature_callback_count);
200 CHECK(v8_str("TypeError: Illegal invocation")
201 ->Equals(try_catch.Exception()->ToString(isolate)));
206 THREADED_TEST(ReceiverSignature) {
208 v8::Isolate* isolate = env->GetIsolate();
209 v8::HandleScope scope(isolate);
211 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
212 v8::Handle<v8::Signature> sig = v8::Signature::New(isolate, fun);
213 v8::Handle<v8::FunctionTemplate> callback_sig =
214 v8::FunctionTemplate::New(
215 isolate, IncrementingSignatureCallback, Local<Value>(), sig);
216 v8::Handle<v8::FunctionTemplate> callback =
217 v8::FunctionTemplate::New(isolate, IncrementingSignatureCallback);
218 v8::Handle<v8::FunctionTemplate> sub_fun = v8::FunctionTemplate::New(isolate);
219 sub_fun->Inherit(fun);
220 v8::Handle<v8::FunctionTemplate> unrel_fun =
221 v8::FunctionTemplate::New(isolate);
222 // Install properties.
223 v8::Handle<v8::ObjectTemplate> fun_proto = fun->PrototypeTemplate();
224 fun_proto->Set(v8_str("prop_sig"), callback_sig);
225 fun_proto->Set(v8_str("prop"), callback);
226 fun_proto->SetAccessorProperty(
227 v8_str("accessor_sig"), callback_sig, callback_sig);
228 fun_proto->SetAccessorProperty(v8_str("accessor"), callback, callback);
229 // Instantiate templates.
230 Local<Value> fun_instance = fun->InstanceTemplate()->NewInstance();
231 Local<Value> sub_fun_instance = sub_fun->InstanceTemplate()->NewInstance();
232 // Setup global variables.
233 env->Global()->Set(v8_str("Fun"), fun->GetFunction());
234 env->Global()->Set(v8_str("UnrelFun"), unrel_fun->GetFunction());
235 env->Global()->Set(v8_str("fun_instance"), fun_instance);
236 env->Global()->Set(v8_str("sub_fun_instance"), sub_fun_instance);
238 "var accessor_sig_key = 'accessor_sig';"
239 "var accessor_key = 'accessor';"
240 "var prop_sig_key = 'prop_sig';"
241 "var prop_key = 'prop';"
243 "function copy_props(obj) {"
244 " var keys = [accessor_sig_key, accessor_key, prop_sig_key, prop_key];"
245 " var source = Fun.prototype;"
246 " for (var i in keys) {"
247 " var key = keys[i];"
248 " var desc = Object.getOwnPropertyDescriptor(source, key);"
249 " Object.defineProperty(obj, key, desc);"
255 "var unrel = new UnrelFun();"
256 "copy_props(unrel);");
257 // Test with and without ICs
258 const char* test_objects[] = {
259 "fun_instance", "sub_fun_instance", "obj", "unrel" };
260 unsigned bad_signature_start_offset = 2;
261 for (unsigned i = 0; i < arraysize(test_objects); i++) {
262 i::ScopedVector<char> source(200);
264 source, "var test_object = %s; test_object", test_objects[i]);
265 Local<Value> test_object = CompileRun(source.start());
266 TestSignature("test_object.prop();", test_object, isolate);
267 TestSignature("test_object.accessor;", test_object, isolate);
268 TestSignature("test_object[accessor_key];", test_object, isolate);
269 TestSignature("test_object.accessor = 1;", test_object, isolate);
270 TestSignature("test_object[accessor_key] = 1;", test_object, isolate);
271 if (i >= bad_signature_start_offset) test_object = Local<Value>();
272 TestSignature("test_object.prop_sig();", test_object, isolate);
273 TestSignature("test_object.accessor_sig;", test_object, isolate);
274 TestSignature("test_object[accessor_sig_key];", test_object, isolate);
275 TestSignature("test_object.accessor_sig = 1;", test_object, isolate);
276 TestSignature("test_object[accessor_sig_key] = 1;", test_object, isolate);
281 THREADED_TEST(HulIgennem) {
283 v8::Isolate* isolate = env->GetIsolate();
284 v8::HandleScope scope(isolate);
285 v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
286 Local<String> undef_str = undef->ToString(isolate);
287 char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
288 undef_str->WriteUtf8(value);
289 CHECK_EQ(0, strcmp(value, "undefined"));
290 i::DeleteArray(value);
294 THREADED_TEST(Access) {
296 v8::Isolate* isolate = env->GetIsolate();
297 v8::HandleScope scope(isolate);
298 Local<v8::Object> obj = v8::Object::New(isolate);
299 Local<Value> foo_before = obj->Get(v8_str("foo"));
300 CHECK(foo_before->IsUndefined());
301 Local<String> bar_str = v8_str("bar");
302 obj->Set(v8_str("foo"), bar_str);
303 Local<Value> foo_after = obj->Get(v8_str("foo"));
304 CHECK(!foo_after->IsUndefined());
305 CHECK(foo_after->IsString());
306 CHECK(bar_str->Equals(foo_after));
310 THREADED_TEST(AccessElement) {
312 v8::HandleScope scope(env->GetIsolate());
313 Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
314 Local<Value> before = obj->Get(1);
315 CHECK(before->IsUndefined());
316 Local<String> bar_str = v8_str("bar");
317 obj->Set(1, bar_str);
318 Local<Value> after = obj->Get(1);
319 CHECK(!after->IsUndefined());
320 CHECK(after->IsString());
321 CHECK(bar_str->Equals(after));
323 Local<v8::Array> value = CompileRun("[\"a\", \"b\"]").As<v8::Array>();
324 CHECK(v8_str("a")->Equals(value->Get(0)));
325 CHECK(v8_str("b")->Equals(value->Get(1)));
329 THREADED_TEST(Script) {
331 v8::HandleScope scope(env->GetIsolate());
332 const char* source = "1 + 2 + 3";
333 Local<Script> script = v8_compile(source);
334 CHECK_EQ(6, script->Run()->Int32Value());
338 class TestResource: public String::ExternalStringResource {
340 explicit TestResource(uint16_t* data, int* counter = NULL,
341 bool owning_data = true)
342 : data_(data), length_(0), counter_(counter), owning_data_(owning_data) {
343 while (data[length_]) ++length_;
347 if (owning_data_) i::DeleteArray(data_);
348 if (counter_ != NULL) ++*counter_;
351 const uint16_t* data() const {
355 size_t length() const {
367 class TestOneByteResource : public String::ExternalOneByteStringResource {
369 explicit TestOneByteResource(const char* data, int* counter = NULL,
372 data_(data + offset),
373 length_(strlen(data) - offset),
376 ~TestOneByteResource() {
377 i::DeleteArray(orig_data_);
378 if (counter_ != NULL) ++*counter_;
381 const char* data() const {
385 size_t length() const {
390 const char* orig_data_;
397 THREADED_TEST(ScriptUsingStringResource) {
398 int dispose_count = 0;
399 const char* c_source = "1 + 2 * 3";
400 uint16_t* two_byte_source = AsciiToTwoByteString(c_source);
403 v8::HandleScope scope(env->GetIsolate());
404 TestResource* resource = new TestResource(two_byte_source, &dispose_count);
405 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
406 Local<Script> script = v8_compile(source);
407 Local<Value> value = script->Run();
408 CHECK(value->IsNumber());
409 CHECK_EQ(7, value->Int32Value());
410 CHECK(source->IsExternal());
412 static_cast<TestResource*>(source->GetExternalStringResource()));
413 String::Encoding encoding = String::UNKNOWN_ENCODING;
414 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
415 source->GetExternalStringResourceBase(&encoding));
416 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
417 CcTest::heap()->CollectAllGarbage();
418 CHECK_EQ(0, dispose_count);
420 CcTest::i_isolate()->compilation_cache()->Clear();
421 CcTest::heap()->CollectAllAvailableGarbage();
422 CHECK_EQ(1, dispose_count);
426 THREADED_TEST(ScriptUsingOneByteStringResource) {
427 int dispose_count = 0;
428 const char* c_source = "1 + 2 * 3";
431 v8::HandleScope scope(env->GetIsolate());
432 TestOneByteResource* resource =
433 new TestOneByteResource(i::StrDup(c_source), &dispose_count);
434 Local<String> source = String::NewExternal(env->GetIsolate(), resource);
435 CHECK(source->IsExternalOneByte());
436 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
437 source->GetExternalOneByteStringResource());
438 String::Encoding encoding = String::UNKNOWN_ENCODING;
439 CHECK_EQ(static_cast<const String::ExternalStringResourceBase*>(resource),
440 source->GetExternalStringResourceBase(&encoding));
441 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
442 Local<Script> script = v8_compile(source);
443 Local<Value> value = script->Run();
444 CHECK(value->IsNumber());
445 CHECK_EQ(7, value->Int32Value());
446 CcTest::heap()->CollectAllGarbage();
447 CHECK_EQ(0, dispose_count);
449 CcTest::i_isolate()->compilation_cache()->Clear();
450 CcTest::heap()->CollectAllAvailableGarbage();
451 CHECK_EQ(1, dispose_count);
455 THREADED_TEST(ScriptMakingExternalString) {
456 int dispose_count = 0;
457 uint16_t* two_byte_source = AsciiToTwoByteString("1 + 2 * 3");
460 v8::HandleScope scope(env->GetIsolate());
461 Local<String> source =
462 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
463 // Trigger GCs so that the newly allocated string moves to old gen.
464 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
465 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
466 CHECK_EQ(source->IsExternal(), false);
467 CHECK_EQ(source->IsExternalOneByte(), false);
468 String::Encoding encoding = String::UNKNOWN_ENCODING;
469 CHECK(!source->GetExternalStringResourceBase(&encoding));
470 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
471 bool success = source->MakeExternal(new TestResource(two_byte_source,
474 Local<Script> script = v8_compile(source);
475 Local<Value> value = script->Run();
476 CHECK(value->IsNumber());
477 CHECK_EQ(7, value->Int32Value());
478 CcTest::heap()->CollectAllGarbage();
479 CHECK_EQ(0, dispose_count);
481 CcTest::i_isolate()->compilation_cache()->Clear();
482 CcTest::heap()->CollectAllGarbage();
483 CHECK_EQ(1, dispose_count);
487 THREADED_TEST(ScriptMakingExternalOneByteString) {
488 int dispose_count = 0;
489 const char* c_source = "1 + 2 * 3";
492 v8::HandleScope scope(env->GetIsolate());
493 Local<String> source = v8_str(c_source);
494 // Trigger GCs so that the newly allocated string moves to old gen.
495 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
496 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
497 bool success = source->MakeExternal(
498 new TestOneByteResource(i::StrDup(c_source), &dispose_count));
500 Local<Script> script = v8_compile(source);
501 Local<Value> value = script->Run();
502 CHECK(value->IsNumber());
503 CHECK_EQ(7, value->Int32Value());
504 CcTest::heap()->CollectAllGarbage();
505 CHECK_EQ(0, dispose_count);
507 CcTest::i_isolate()->compilation_cache()->Clear();
508 CcTest::heap()->CollectAllGarbage();
509 CHECK_EQ(1, dispose_count);
513 TEST(MakingExternalStringConditions) {
515 v8::HandleScope scope(env->GetIsolate());
517 // Free some space in the new space so that we can check freshness.
518 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
519 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
521 uint16_t* two_byte_string = AsciiToTwoByteString("s1");
522 Local<String> small_string =
523 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
524 i::DeleteArray(two_byte_string);
526 // We should refuse to externalize small strings.
527 CHECK(!small_string->CanMakeExternal());
528 // Trigger GCs so that the newly allocated string moves to old gen.
529 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
530 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
531 // Old space strings should be accepted.
532 CHECK(small_string->CanMakeExternal());
534 two_byte_string = AsciiToTwoByteString("small string 2");
535 small_string = String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
536 i::DeleteArray(two_byte_string);
538 const int buf_size = 10 * 1024;
539 char* buf = i::NewArray<char>(buf_size);
540 memset(buf, 'a', buf_size);
541 buf[buf_size - 1] = '\0';
543 two_byte_string = AsciiToTwoByteString(buf);
544 Local<String> large_string =
545 String::NewFromTwoByte(env->GetIsolate(), two_byte_string);
547 i::DeleteArray(two_byte_string);
548 // Large strings should be immediately accepted.
549 CHECK(large_string->CanMakeExternal());
553 TEST(MakingExternalOneByteStringConditions) {
555 v8::HandleScope scope(env->GetIsolate());
557 // Free some space in the new space so that we can check freshness.
558 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
559 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
561 Local<String> small_string = String::NewFromUtf8(env->GetIsolate(), "s1");
562 // We should refuse to externalize small strings.
563 CHECK(!small_string->CanMakeExternal());
564 // Trigger GCs so that the newly allocated string moves to old gen.
565 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
566 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
567 // Old space strings should be accepted.
568 CHECK(small_string->CanMakeExternal());
570 const int buf_size = 10 * 1024;
571 char* buf = i::NewArray<char>(buf_size);
572 memset(buf, 'a', buf_size);
573 buf[buf_size - 1] = '\0';
574 Local<String> large_string = String::NewFromUtf8(env->GetIsolate(), buf);
576 // Large strings should be immediately accepted.
577 CHECK(large_string->CanMakeExternal());
581 TEST(MakingExternalUnalignedOneByteString) {
583 v8::HandleScope scope(env->GetIsolate());
585 CompileRun("function cons(a, b) { return a + b; }"
586 "function slice(a) { return a.substring(1); }");
587 // Create a cons string that will land in old pointer space.
588 Local<String> cons = Local<String>::Cast(CompileRun(
589 "cons('abcdefghijklm', 'nopqrstuvwxyz');"));
590 // Create a sliced string that will land in old pointer space.
591 Local<String> slice = Local<String>::Cast(CompileRun(
592 "slice('abcdefghijklmnopqrstuvwxyz');"));
594 // Trigger GCs so that the newly allocated string moves to old gen.
595 SimulateFullSpace(CcTest::heap()->old_space());
596 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
597 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
599 // Turn into external string with unaligned resource data.
600 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz";
602 cons->MakeExternal(new TestOneByteResource(i::StrDup(c_cons), NULL, 1));
604 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz";
606 slice->MakeExternal(new TestOneByteResource(i::StrDup(c_slice), NULL, 1));
609 // Trigger GCs and force evacuation.
610 CcTest::heap()->CollectAllGarbage();
611 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask);
615 THREADED_TEST(UsingExternalString) {
616 i::Factory* factory = CcTest::i_isolate()->factory();
618 v8::HandleScope scope(CcTest::isolate());
619 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
620 Local<String> string = String::NewExternal(
621 CcTest::isolate(), new TestResource(two_byte_string));
622 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
623 // Trigger GCs so that the newly allocated string moves to old gen.
624 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
625 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
626 i::Handle<i::String> isymbol =
627 factory->InternalizeString(istring);
628 CHECK(isymbol->IsInternalizedString());
630 CcTest::heap()->CollectAllGarbage();
631 CcTest::heap()->CollectAllGarbage();
635 THREADED_TEST(UsingExternalOneByteString) {
636 i::Factory* factory = CcTest::i_isolate()->factory();
638 v8::HandleScope scope(CcTest::isolate());
639 const char* one_byte_string = "test string";
640 Local<String> string = String::NewExternal(
641 CcTest::isolate(), new TestOneByteResource(i::StrDup(one_byte_string)));
642 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
643 // Trigger GCs so that the newly allocated string moves to old gen.
644 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now
645 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now
646 i::Handle<i::String> isymbol =
647 factory->InternalizeString(istring);
648 CHECK(isymbol->IsInternalizedString());
650 CcTest::heap()->CollectAllGarbage();
651 CcTest::heap()->CollectAllGarbage();
655 class RandomLengthResource : public v8::String::ExternalStringResource {
657 explicit RandomLengthResource(int length) : length_(length) {}
658 virtual const uint16_t* data() const { return string_; }
659 virtual size_t length() const { return length_; }
662 uint16_t string_[10];
667 class RandomLengthOneByteResource
668 : public v8::String::ExternalOneByteStringResource {
670 explicit RandomLengthOneByteResource(int length) : length_(length) {}
671 virtual const char* data() const { return string_; }
672 virtual size_t length() const { return length_; }
680 THREADED_TEST(NewExternalForVeryLongString) {
681 auto isolate = CcTest::isolate();
683 v8::HandleScope scope(isolate);
684 v8::TryCatch try_catch(isolate);
685 RandomLengthOneByteResource r(1 << 30);
686 v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
687 CHECK(str.IsEmpty());
688 CHECK(!try_catch.HasCaught());
692 v8::HandleScope scope(isolate);
693 v8::TryCatch try_catch(isolate);
694 RandomLengthResource r(1 << 30);
695 v8::Local<v8::String> str = v8::String::NewExternal(isolate, &r);
696 CHECK(str.IsEmpty());
697 CHECK(!try_catch.HasCaught());
702 THREADED_TEST(ScavengeExternalString) {
703 i::FLAG_stress_compaction = false;
704 i::FLAG_gc_global = false;
705 int dispose_count = 0;
706 bool in_new_space = false;
708 v8::HandleScope scope(CcTest::isolate());
709 uint16_t* two_byte_string = AsciiToTwoByteString("test string");
710 Local<String> string = String::NewExternal(
711 CcTest::isolate(), new TestResource(two_byte_string, &dispose_count));
712 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
713 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
714 in_new_space = CcTest::heap()->InNewSpace(*istring);
715 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
716 CHECK_EQ(0, dispose_count);
718 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
719 CHECK_EQ(1, dispose_count);
723 THREADED_TEST(ScavengeExternalOneByteString) {
724 i::FLAG_stress_compaction = false;
725 i::FLAG_gc_global = false;
726 int dispose_count = 0;
727 bool in_new_space = false;
729 v8::HandleScope scope(CcTest::isolate());
730 const char* one_byte_string = "test string";
731 Local<String> string = String::NewExternal(
733 new TestOneByteResource(i::StrDup(one_byte_string), &dispose_count));
734 i::Handle<i::String> istring = v8::Utils::OpenHandle(*string);
735 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
736 in_new_space = CcTest::heap()->InNewSpace(*istring);
737 CHECK(in_new_space || CcTest::heap()->old_space()->Contains(*istring));
738 CHECK_EQ(0, dispose_count);
740 CcTest::heap()->CollectGarbage(in_new_space ? i::NEW_SPACE : i::OLD_SPACE);
741 CHECK_EQ(1, dispose_count);
745 class TestOneByteResourceWithDisposeControl : public TestOneByteResource {
747 // Only used by non-threaded tests, so it can use static fields.
748 static int dispose_calls;
749 static int dispose_count;
751 TestOneByteResourceWithDisposeControl(const char* data, bool dispose)
752 : TestOneByteResource(data, &dispose_count), dispose_(dispose) {}
756 if (dispose_) delete this;
763 int TestOneByteResourceWithDisposeControl::dispose_count = 0;
764 int TestOneByteResourceWithDisposeControl::dispose_calls = 0;
767 TEST(ExternalStringWithDisposeHandling) {
768 const char* c_source = "1 + 2 * 3";
770 // Use a stack allocated external string resource allocated object.
771 TestOneByteResourceWithDisposeControl::dispose_count = 0;
772 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
773 TestOneByteResourceWithDisposeControl res_stack(i::StrDup(c_source), false);
776 v8::HandleScope scope(env->GetIsolate());
777 Local<String> source = String::NewExternal(env->GetIsolate(), &res_stack);
778 Local<Script> script = v8_compile(source);
779 Local<Value> value = script->Run();
780 CHECK(value->IsNumber());
781 CHECK_EQ(7, value->Int32Value());
782 CcTest::heap()->CollectAllAvailableGarbage();
783 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
785 CcTest::i_isolate()->compilation_cache()->Clear();
786 CcTest::heap()->CollectAllAvailableGarbage();
787 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
788 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
790 // Use a heap allocated external string resource allocated object.
791 TestOneByteResourceWithDisposeControl::dispose_count = 0;
792 TestOneByteResourceWithDisposeControl::dispose_calls = 0;
793 TestOneByteResource* res_heap =
794 new TestOneByteResourceWithDisposeControl(i::StrDup(c_source), true);
797 v8::HandleScope scope(env->GetIsolate());
798 Local<String> source = String::NewExternal(env->GetIsolate(), res_heap);
799 Local<Script> script = v8_compile(source);
800 Local<Value> value = script->Run();
801 CHECK(value->IsNumber());
802 CHECK_EQ(7, value->Int32Value());
803 CcTest::heap()->CollectAllAvailableGarbage();
804 CHECK_EQ(0, TestOneByteResourceWithDisposeControl::dispose_count);
806 CcTest::i_isolate()->compilation_cache()->Clear();
807 CcTest::heap()->CollectAllAvailableGarbage();
808 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_calls);
809 CHECK_EQ(1, TestOneByteResourceWithDisposeControl::dispose_count);
813 THREADED_TEST(StringConcat) {
816 v8::HandleScope scope(env->GetIsolate());
817 const char* one_byte_string_1 = "function a_times_t";
818 const char* two_byte_string_1 = "wo_plus_b(a, b) {return ";
819 const char* one_byte_extern_1 = "a * 2 + b;} a_times_two_plus_b(4, 8) + ";
820 const char* two_byte_extern_1 = "a_times_two_plus_b(4, 8) + ";
821 const char* one_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
822 const char* two_byte_string_2 = "a_times_two_plus_b(4, 8) + ";
823 const char* two_byte_extern_2 = "a_times_two_plus_b(1, 2);";
824 Local<String> left = v8_str(one_byte_string_1);
826 uint16_t* two_byte_source = AsciiToTwoByteString(two_byte_string_1);
827 Local<String> right =
828 String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
829 i::DeleteArray(two_byte_source);
831 Local<String> source = String::Concat(left, right);
832 right = String::NewExternal(
834 new TestOneByteResource(i::StrDup(one_byte_extern_1)));
835 source = String::Concat(source, right);
836 right = String::NewExternal(
838 new TestResource(AsciiToTwoByteString(two_byte_extern_1)));
839 source = String::Concat(source, right);
840 right = v8_str(one_byte_string_2);
841 source = String::Concat(source, right);
843 two_byte_source = AsciiToTwoByteString(two_byte_string_2);
844 right = String::NewFromTwoByte(env->GetIsolate(), two_byte_source);
845 i::DeleteArray(two_byte_source);
847 source = String::Concat(source, right);
848 right = String::NewExternal(
850 new TestResource(AsciiToTwoByteString(two_byte_extern_2)));
851 source = String::Concat(source, right);
852 Local<Script> script = v8_compile(source);
853 Local<Value> value = script->Run();
854 CHECK(value->IsNumber());
855 CHECK_EQ(68, value->Int32Value());
857 CcTest::i_isolate()->compilation_cache()->Clear();
858 CcTest::heap()->CollectAllGarbage();
859 CcTest::heap()->CollectAllGarbage();
863 THREADED_TEST(GlobalProperties) {
865 v8::HandleScope scope(env->GetIsolate());
866 v8::Handle<v8::Object> global = env->Global();
867 global->Set(v8_str("pi"), v8_num(3.1415926));
868 Local<Value> pi = global->Get(v8_str("pi"));
869 CHECK_EQ(3.1415926, pi->NumberValue());
873 static void handle_callback_impl(const v8::FunctionCallbackInfo<Value>& info,
874 i::Address callback) {
875 ApiTestFuzzer::Fuzz();
876 CheckReturnValue(info, callback);
877 info.GetReturnValue().Set(v8_str("bad value"));
878 info.GetReturnValue().Set(v8_num(102));
882 static void handle_callback(const v8::FunctionCallbackInfo<Value>& info) {
883 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback));
887 static void handle_callback_2(const v8::FunctionCallbackInfo<Value>& info) {
888 return handle_callback_impl(info, FUNCTION_ADDR(handle_callback_2));
891 static void construct_callback(
892 const v8::FunctionCallbackInfo<Value>& info) {
893 ApiTestFuzzer::Fuzz();
894 CheckReturnValue(info, FUNCTION_ADDR(construct_callback));
895 info.This()->Set(v8_str("x"), v8_num(1));
896 info.This()->Set(v8_str("y"), v8_num(2));
897 info.GetReturnValue().Set(v8_str("bad value"));
898 info.GetReturnValue().Set(info.This());
902 static void Return239Callback(
903 Local<String> name, const v8::PropertyCallbackInfo<Value>& info) {
904 ApiTestFuzzer::Fuzz();
905 CheckReturnValue(info, FUNCTION_ADDR(Return239Callback));
906 info.GetReturnValue().Set(v8_str("bad value"));
907 info.GetReturnValue().Set(v8_num(239));
911 template<typename Handler>
912 static void TestFunctionTemplateInitializer(Handler handler,
914 // Test constructor calls.
917 v8::Isolate* isolate = env->GetIsolate();
918 v8::HandleScope scope(isolate);
920 Local<v8::FunctionTemplate> fun_templ =
921 v8::FunctionTemplate::New(isolate, handler);
922 Local<Function> fun = fun_templ->GetFunction();
923 env->Global()->Set(v8_str("obj"), fun);
924 Local<Script> script = v8_compile("obj()");
925 for (int i = 0; i < 30; i++) {
926 CHECK_EQ(102, script->Run()->Int32Value());
929 // Use SetCallHandler to initialize a function template, should work like
933 v8::Isolate* isolate = env->GetIsolate();
934 v8::HandleScope scope(isolate);
936 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(isolate);
937 fun_templ->SetCallHandler(handler_2);
938 Local<Function> fun = fun_templ->GetFunction();
939 env->Global()->Set(v8_str("obj"), fun);
940 Local<Script> script = v8_compile("obj()");
941 for (int i = 0; i < 30; i++) {
942 CHECK_EQ(102, script->Run()->Int32Value());
948 template<typename Constructor, typename Accessor>
949 static void TestFunctionTemplateAccessor(Constructor constructor,
952 v8::HandleScope scope(env->GetIsolate());
954 Local<v8::FunctionTemplate> fun_templ =
955 v8::FunctionTemplate::New(env->GetIsolate(), constructor);
956 fun_templ->SetClassName(v8_str("funky"));
957 fun_templ->InstanceTemplate()->SetAccessor(v8_str("m"), accessor);
958 Local<Function> fun = fun_templ->GetFunction();
959 env->Global()->Set(v8_str("obj"), fun);
960 Local<Value> result = v8_compile("(new obj()).toString()")->Run();
961 CHECK(v8_str("[object funky]")->Equals(result));
962 CompileRun("var obj_instance = new obj();");
963 Local<Script> script;
964 script = v8_compile("obj_instance.x");
965 for (int i = 0; i < 30; i++) {
966 CHECK_EQ(1, script->Run()->Int32Value());
968 script = v8_compile("obj_instance.m");
969 for (int i = 0; i < 30; i++) {
970 CHECK_EQ(239, script->Run()->Int32Value());
975 THREADED_PROFILED_TEST(FunctionTemplate) {
976 TestFunctionTemplateInitializer(handle_callback, handle_callback_2);
977 TestFunctionTemplateAccessor(construct_callback, Return239Callback);
981 static void SimpleCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
982 ApiTestFuzzer::Fuzz();
983 CheckReturnValue(info, FUNCTION_ADDR(SimpleCallback));
984 info.GetReturnValue().Set(v8_num(51423 + info.Length()));
988 template<typename Callback>
989 static void TestSimpleCallback(Callback callback) {
991 v8::Isolate* isolate = env->GetIsolate();
992 v8::HandleScope scope(isolate);
994 v8::Handle<v8::ObjectTemplate> object_template =
995 v8::ObjectTemplate::New(isolate);
996 object_template->Set(isolate, "callback",
997 v8::FunctionTemplate::New(isolate, callback));
998 v8::Local<v8::Object> object = object_template->NewInstance();
999 (*env)->Global()->Set(v8_str("callback_object"), object);
1000 v8::Handle<v8::Script> script;
1001 script = v8_compile("callback_object.callback(17)");
1002 for (int i = 0; i < 30; i++) {
1003 CHECK_EQ(51424, script->Run()->Int32Value());
1005 script = v8_compile("callback_object.callback(17, 24)");
1006 for (int i = 0; i < 30; i++) {
1007 CHECK_EQ(51425, script->Run()->Int32Value());
1012 THREADED_PROFILED_TEST(SimpleCallback) {
1013 TestSimpleCallback(SimpleCallback);
1017 template<typename T>
1018 void FastReturnValueCallback(const v8::FunctionCallbackInfo<v8::Value>& info);
1020 // constant return values
1021 static int32_t fast_return_value_int32 = 471;
1022 static uint32_t fast_return_value_uint32 = 571;
1023 static const double kFastReturnValueDouble = 2.7;
1024 // variable return values
1025 static bool fast_return_value_bool = false;
1026 enum ReturnValueOddball {
1028 kUndefinedReturnValue,
1029 kEmptyStringReturnValue
1031 static ReturnValueOddball fast_return_value_void;
1032 static bool fast_return_value_object_is_empty = false;
1034 // Helper function to avoid compiler error: insufficient contextual information
1035 // to determine type when applying FUNCTION_ADDR to a template function.
1036 static i::Address address_of(v8::FunctionCallback callback) {
1037 return FUNCTION_ADDR(callback);
1041 void FastReturnValueCallback<int32_t>(
1042 const v8::FunctionCallbackInfo<v8::Value>& info) {
1043 CheckReturnValue(info, address_of(FastReturnValueCallback<int32_t>));
1044 info.GetReturnValue().Set(fast_return_value_int32);
1048 void FastReturnValueCallback<uint32_t>(
1049 const v8::FunctionCallbackInfo<v8::Value>& info) {
1050 CheckReturnValue(info, address_of(FastReturnValueCallback<uint32_t>));
1051 info.GetReturnValue().Set(fast_return_value_uint32);
1055 void FastReturnValueCallback<double>(
1056 const v8::FunctionCallbackInfo<v8::Value>& info) {
1057 CheckReturnValue(info, address_of(FastReturnValueCallback<double>));
1058 info.GetReturnValue().Set(kFastReturnValueDouble);
1062 void FastReturnValueCallback<bool>(
1063 const v8::FunctionCallbackInfo<v8::Value>& info) {
1064 CheckReturnValue(info, address_of(FastReturnValueCallback<bool>));
1065 info.GetReturnValue().Set(fast_return_value_bool);
1069 void FastReturnValueCallback<void>(
1070 const v8::FunctionCallbackInfo<v8::Value>& info) {
1071 CheckReturnValue(info, address_of(FastReturnValueCallback<void>));
1072 switch (fast_return_value_void) {
1073 case kNullReturnValue:
1074 info.GetReturnValue().SetNull();
1076 case kUndefinedReturnValue:
1077 info.GetReturnValue().SetUndefined();
1079 case kEmptyStringReturnValue:
1080 info.GetReturnValue().SetEmptyString();
1086 void FastReturnValueCallback<Object>(
1087 const v8::FunctionCallbackInfo<v8::Value>& info) {
1088 v8::Handle<v8::Object> object;
1089 if (!fast_return_value_object_is_empty) {
1090 object = Object::New(info.GetIsolate());
1092 info.GetReturnValue().Set(object);
1095 template<typename T>
1096 Handle<Value> TestFastReturnValues() {
1098 v8::Isolate* isolate = env->GetIsolate();
1099 v8::EscapableHandleScope scope(isolate);
1100 v8::Handle<v8::ObjectTemplate> object_template =
1101 v8::ObjectTemplate::New(isolate);
1102 v8::FunctionCallback callback = &FastReturnValueCallback<T>;
1103 object_template->Set(isolate, "callback",
1104 v8::FunctionTemplate::New(isolate, callback));
1105 v8::Local<v8::Object> object = object_template->NewInstance();
1106 (*env)->Global()->Set(v8_str("callback_object"), object);
1107 return scope.Escape(CompileRun("callback_object.callback()"));
1111 THREADED_PROFILED_TEST(FastReturnValues) {
1113 v8::Isolate* isolate = env->GetIsolate();
1114 v8::HandleScope scope(isolate);
1115 v8::Handle<v8::Value> value;
1116 // check int32_t and uint32_t
1117 int32_t int_values[] = {
1119 i::Smi::kMinValue, i::Smi::kMaxValue
1121 for (size_t i = 0; i < arraysize(int_values); i++) {
1122 for (int modifier = -1; modifier <= 1; modifier++) {
1123 int int_value = int_values[i] + modifier;
1125 fast_return_value_int32 = int_value;
1126 value = TestFastReturnValues<int32_t>();
1127 CHECK(value->IsInt32());
1128 CHECK(fast_return_value_int32 == value->Int32Value());
1130 fast_return_value_uint32 = static_cast<uint32_t>(int_value);
1131 value = TestFastReturnValues<uint32_t>();
1132 CHECK(value->IsUint32());
1133 CHECK(fast_return_value_uint32 == value->Uint32Value());
1137 value = TestFastReturnValues<double>();
1138 CHECK(value->IsNumber());
1139 CHECK_EQ(kFastReturnValueDouble, value->ToNumber(isolate)->Value());
1140 // check bool values
1141 for (int i = 0; i < 2; i++) {
1142 fast_return_value_bool = i == 0;
1143 value = TestFastReturnValues<bool>();
1144 CHECK(value->IsBoolean());
1145 CHECK_EQ(fast_return_value_bool, value->ToBoolean(isolate)->Value());
1148 ReturnValueOddball oddballs[] = {
1150 kUndefinedReturnValue,
1151 kEmptyStringReturnValue
1153 for (size_t i = 0; i < arraysize(oddballs); i++) {
1154 fast_return_value_void = oddballs[i];
1155 value = TestFastReturnValues<void>();
1156 switch (fast_return_value_void) {
1157 case kNullReturnValue:
1158 CHECK(value->IsNull());
1160 case kUndefinedReturnValue:
1161 CHECK(value->IsUndefined());
1163 case kEmptyStringReturnValue:
1164 CHECK(value->IsString());
1165 CHECK_EQ(0, v8::String::Cast(*value)->Length());
1170 fast_return_value_object_is_empty = false;
1171 value = TestFastReturnValues<Object>();
1172 CHECK(value->IsObject());
1173 fast_return_value_object_is_empty = true;
1174 value = TestFastReturnValues<Object>();
1175 CHECK(value->IsUndefined());
1179 THREADED_TEST(FunctionTemplateSetLength) {
1181 v8::Isolate* isolate = env->GetIsolate();
1182 v8::HandleScope scope(isolate);
1184 Local<v8::FunctionTemplate> fun_templ =
1185 v8::FunctionTemplate::New(isolate,
1187 Handle<v8::Value>(),
1188 Handle<v8::Signature>(),
1190 Local<Function> fun = fun_templ->GetFunction();
1191 env->Global()->Set(v8_str("obj"), fun);
1192 Local<Script> script = v8_compile("obj.length");
1193 CHECK_EQ(23, script->Run()->Int32Value());
1196 Local<v8::FunctionTemplate> fun_templ =
1197 v8::FunctionTemplate::New(isolate, handle_callback);
1198 fun_templ->SetLength(22);
1199 Local<Function> fun = fun_templ->GetFunction();
1200 env->Global()->Set(v8_str("obj"), fun);
1201 Local<Script> script = v8_compile("obj.length");
1202 CHECK_EQ(22, script->Run()->Int32Value());
1205 // Without setting length it defaults to 0.
1206 Local<v8::FunctionTemplate> fun_templ =
1207 v8::FunctionTemplate::New(isolate, handle_callback);
1208 Local<Function> fun = fun_templ->GetFunction();
1209 env->Global()->Set(v8_str("obj"), fun);
1210 Local<Script> script = v8_compile("obj.length");
1211 CHECK_EQ(0, script->Run()->Int32Value());
1216 static void* expected_ptr;
1217 static void callback(const v8::FunctionCallbackInfo<v8::Value>& args) {
1218 void* ptr = v8::External::Cast(*args.Data())->Value();
1219 CHECK_EQ(expected_ptr, ptr);
1220 args.GetReturnValue().Set(true);
1224 static void TestExternalPointerWrapping() {
1226 v8::Isolate* isolate = env->GetIsolate();
1227 v8::HandleScope scope(isolate);
1229 v8::Handle<v8::Value> data =
1230 v8::External::New(isolate, expected_ptr);
1232 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
1233 obj->Set(v8_str("func"),
1234 v8::FunctionTemplate::New(isolate, callback, data)->GetFunction());
1235 env->Global()->Set(v8_str("obj"), obj);
1238 "function foo() {\n"
1239 " for (var i = 0; i < 13; i++) obj.func();\n"
1241 "foo(), true")->BooleanValue());
1245 THREADED_TEST(ExternalWrap) {
1246 // Check heap allocated object.
1249 TestExternalPointerWrapping();
1252 // Check stack allocated object.
1254 expected_ptr = &foo;
1255 TestExternalPointerWrapping();
1257 // Check not aligned addresses.
1259 char* s = new char[n];
1260 for (int i = 0; i < n; i++) {
1261 expected_ptr = s + i;
1262 TestExternalPointerWrapping();
1267 // Check several invalid addresses.
1268 expected_ptr = reinterpret_cast<void*>(1);
1269 TestExternalPointerWrapping();
1271 expected_ptr = reinterpret_cast<void*>(0xdeadbeef);
1272 TestExternalPointerWrapping();
1274 expected_ptr = reinterpret_cast<void*>(0xdeadbeef + 1);
1275 TestExternalPointerWrapping();
1277 #if defined(V8_HOST_ARCH_X64)
1278 // Check a value with a leading 1 bit in x64 Smi encoding.
1279 expected_ptr = reinterpret_cast<void*>(0x400000000);
1280 TestExternalPointerWrapping();
1282 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef);
1283 TestExternalPointerWrapping();
1285 expected_ptr = reinterpret_cast<void*>(0xdeadbeefdeadbeef + 1);
1286 TestExternalPointerWrapping();
1291 THREADED_TEST(FindInstanceInPrototypeChain) {
1293 v8::Isolate* isolate = env->GetIsolate();
1294 v8::HandleScope scope(isolate);
1296 Local<v8::FunctionTemplate> base = v8::FunctionTemplate::New(isolate);
1297 Local<v8::FunctionTemplate> derived = v8::FunctionTemplate::New(isolate);
1298 Local<v8::FunctionTemplate> other = v8::FunctionTemplate::New(isolate);
1299 derived->Inherit(base);
1301 Local<v8::Function> base_function = base->GetFunction();
1302 Local<v8::Function> derived_function = derived->GetFunction();
1303 Local<v8::Function> other_function = other->GetFunction();
1305 Local<v8::Object> base_instance = base_function->NewInstance();
1306 Local<v8::Object> derived_instance = derived_function->NewInstance();
1307 Local<v8::Object> derived_instance2 = derived_function->NewInstance();
1308 Local<v8::Object> other_instance = other_function->NewInstance();
1309 derived_instance2->Set(v8_str("__proto__"), derived_instance);
1310 other_instance->Set(v8_str("__proto__"), derived_instance2);
1312 // base_instance is only an instance of base.
1314 base_instance->Equals(base_instance->FindInstanceInPrototypeChain(base)));
1315 CHECK(base_instance->FindInstanceInPrototypeChain(derived).IsEmpty());
1316 CHECK(base_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1318 // derived_instance is an instance of base and derived.
1319 CHECK(derived_instance->Equals(
1320 derived_instance->FindInstanceInPrototypeChain(base)));
1321 CHECK(derived_instance->Equals(
1322 derived_instance->FindInstanceInPrototypeChain(derived)));
1323 CHECK(derived_instance->FindInstanceInPrototypeChain(other).IsEmpty());
1325 // other_instance is an instance of other and its immediate
1326 // prototype derived_instance2 is an instance of base and derived.
1327 // Note, derived_instance is an instance of base and derived too,
1328 // but it comes after derived_instance2 in the prototype chain of
1330 CHECK(derived_instance2->Equals(
1331 other_instance->FindInstanceInPrototypeChain(base)));
1332 CHECK(derived_instance2->Equals(
1333 other_instance->FindInstanceInPrototypeChain(derived)));
1334 CHECK(other_instance->Equals(
1335 other_instance->FindInstanceInPrototypeChain(other)));
1339 THREADED_TEST(TinyInteger) {
1341 v8::Isolate* isolate = env->GetIsolate();
1342 v8::HandleScope scope(isolate);
1344 int32_t value = 239;
1345 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1346 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1348 value_obj = v8::Integer::New(isolate, value);
1349 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1353 THREADED_TEST(BigSmiInteger) {
1355 v8::HandleScope scope(env->GetIsolate());
1356 v8::Isolate* isolate = CcTest::isolate();
1358 int32_t value = i::Smi::kMaxValue;
1359 // We cannot add one to a Smi::kMaxValue without wrapping.
1360 if (i::SmiValuesAre31Bits()) {
1361 CHECK(i::Smi::IsValid(value));
1362 CHECK(!i::Smi::IsValid(value + 1));
1364 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1365 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1367 value_obj = v8::Integer::New(isolate, value);
1368 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1373 THREADED_TEST(BigInteger) {
1375 v8::HandleScope scope(env->GetIsolate());
1376 v8::Isolate* isolate = CcTest::isolate();
1378 // We cannot add one to a Smi::kMaxValue without wrapping.
1379 if (i::SmiValuesAre31Bits()) {
1380 // The casts allow this to compile, even if Smi::kMaxValue is 2^31-1.
1381 // The code will not be run in that case, due to the "if" guard.
1383 static_cast<int32_t>(static_cast<uint32_t>(i::Smi::kMaxValue) + 1);
1384 CHECK(value > i::Smi::kMaxValue);
1385 CHECK(!i::Smi::IsValid(value));
1387 Local<v8::Integer> value_obj = v8::Integer::New(isolate, value);
1388 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1390 value_obj = v8::Integer::New(isolate, value);
1391 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1396 THREADED_TEST(TinyUnsignedInteger) {
1398 v8::HandleScope scope(env->GetIsolate());
1399 v8::Isolate* isolate = CcTest::isolate();
1401 uint32_t value = 239;
1403 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1404 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1406 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1407 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1411 THREADED_TEST(BigUnsignedSmiInteger) {
1413 v8::HandleScope scope(env->GetIsolate());
1414 v8::Isolate* isolate = CcTest::isolate();
1416 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue);
1417 CHECK(i::Smi::IsValid(value));
1418 CHECK(!i::Smi::IsValid(value + 1));
1420 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1421 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1423 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1424 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1428 THREADED_TEST(BigUnsignedInteger) {
1430 v8::HandleScope scope(env->GetIsolate());
1431 v8::Isolate* isolate = CcTest::isolate();
1433 uint32_t value = static_cast<uint32_t>(i::Smi::kMaxValue) + 1;
1434 CHECK(value > static_cast<uint32_t>(i::Smi::kMaxValue));
1435 CHECK(!i::Smi::IsValid(value));
1437 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1438 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1440 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1441 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1445 THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
1447 v8::HandleScope scope(env->GetIsolate());
1448 v8::Isolate* isolate = CcTest::isolate();
1450 uint32_t INT32_MAX_AS_UINT = (1U << 31) - 1;
1451 uint32_t value = INT32_MAX_AS_UINT + 1;
1452 CHECK(value > INT32_MAX_AS_UINT); // No overflow.
1454 Local<v8::Integer> value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1455 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1457 value_obj = v8::Integer::NewFromUnsigned(isolate, value);
1458 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value());
1462 THREADED_TEST(IsNativeError) {
1464 v8::HandleScope scope(env->GetIsolate());
1465 v8::Handle<Value> syntax_error = CompileRun(
1466 "var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
1467 CHECK(syntax_error->IsNativeError());
1468 v8::Handle<Value> not_error = CompileRun("{a:42}");
1469 CHECK(!not_error->IsNativeError());
1470 v8::Handle<Value> not_object = CompileRun("42");
1471 CHECK(!not_object->IsNativeError());
1475 THREADED_TEST(IsGeneratorFunctionOrObject) {
1477 v8::HandleScope scope(env->GetIsolate());
1479 CompileRun("function *gen() { yield 1; }\nfunction func() {}");
1480 v8::Handle<Value> gen = CompileRun("gen");
1481 v8::Handle<Value> genObj = CompileRun("gen()");
1482 v8::Handle<Value> object = CompileRun("{a:42}");
1483 v8::Handle<Value> func = CompileRun("func");
1485 CHECK(gen->IsGeneratorFunction());
1486 CHECK(gen->IsFunction());
1487 CHECK(!gen->IsGeneratorObject());
1489 CHECK(!genObj->IsGeneratorFunction());
1490 CHECK(!genObj->IsFunction());
1491 CHECK(genObj->IsGeneratorObject());
1493 CHECK(!object->IsGeneratorFunction());
1494 CHECK(!object->IsFunction());
1495 CHECK(!object->IsGeneratorObject());
1497 CHECK(!func->IsGeneratorFunction());
1498 CHECK(func->IsFunction());
1499 CHECK(!func->IsGeneratorObject());
1503 THREADED_TEST(ArgumentsObject) {
1505 v8::HandleScope scope(env->GetIsolate());
1506 v8::Handle<Value> arguments_object =
1507 CompileRun("var out = 0; (function(){ out = arguments; })(1,2,3); out;");
1508 CHECK(arguments_object->IsArgumentsObject());
1509 v8::Handle<Value> array = CompileRun("[1,2,3]");
1510 CHECK(!array->IsArgumentsObject());
1511 v8::Handle<Value> object = CompileRun("{a:42}");
1512 CHECK(!object->IsArgumentsObject());
1516 THREADED_TEST(IsMapOrSet) {
1518 v8::HandleScope scope(env->GetIsolate());
1519 v8::Handle<Value> map = CompileRun("new Map()");
1520 v8::Handle<Value> set = CompileRun("new Set()");
1521 v8::Handle<Value> weak_map = CompileRun("new WeakMap()");
1522 v8::Handle<Value> weak_set = CompileRun("new WeakSet()");
1523 CHECK(map->IsMap());
1524 CHECK(set->IsSet());
1525 CHECK(weak_map->IsWeakMap());
1526 CHECK(weak_set->IsWeakSet());
1528 CHECK(!map->IsSet());
1529 CHECK(!map->IsWeakMap());
1530 CHECK(!map->IsWeakSet());
1532 CHECK(!set->IsMap());
1533 CHECK(!set->IsWeakMap());
1534 CHECK(!set->IsWeakSet());
1536 CHECK(!weak_map->IsMap());
1537 CHECK(!weak_map->IsSet());
1538 CHECK(!weak_map->IsWeakSet());
1540 CHECK(!weak_set->IsMap());
1541 CHECK(!weak_set->IsSet());
1542 CHECK(!weak_set->IsWeakMap());
1544 v8::Handle<Value> object = CompileRun("{a:42}");
1545 CHECK(!object->IsMap());
1546 CHECK(!object->IsSet());
1547 CHECK(!object->IsWeakMap());
1548 CHECK(!object->IsWeakSet());
1552 THREADED_TEST(StringObject) {
1554 v8::HandleScope scope(env->GetIsolate());
1555 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1556 CHECK(boxed_string->IsStringObject());
1557 v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
1558 CHECK(!unboxed_string->IsStringObject());
1559 v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
1560 CHECK(!boxed_not_string->IsStringObject());
1561 v8::Handle<Value> not_object = CompileRun("0");
1562 CHECK(!not_object->IsStringObject());
1563 v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
1564 CHECK(!as_boxed.IsEmpty());
1565 Local<v8::String> the_string = as_boxed->ValueOf();
1566 CHECK(!the_string.IsEmpty());
1567 ExpectObject("\"test\"", the_string);
1568 v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
1569 CHECK(new_boxed_string->IsStringObject());
1570 as_boxed = new_boxed_string.As<v8::StringObject>();
1571 the_string = as_boxed->ValueOf();
1572 CHECK(!the_string.IsEmpty());
1573 ExpectObject("\"test\"", the_string);
1577 TEST(StringObjectDelete) {
1578 LocalContext context;
1579 v8::HandleScope scope(context->GetIsolate());
1580 v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
1581 CHECK(boxed_string->IsStringObject());
1582 v8::Handle<v8::Object> str_obj = boxed_string.As<v8::Object>();
1583 CHECK(!str_obj->Delete(2));
1584 CHECK(!str_obj->Delete(v8_num(2)));
1588 THREADED_TEST(NumberObject) {
1590 v8::HandleScope scope(env->GetIsolate());
1591 v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
1592 CHECK(boxed_number->IsNumberObject());
1593 v8::Handle<Value> unboxed_number = CompileRun("42");
1594 CHECK(!unboxed_number->IsNumberObject());
1595 v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
1596 CHECK(!boxed_not_number->IsNumberObject());
1597 v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
1598 CHECK(!as_boxed.IsEmpty());
1599 double the_number = as_boxed->ValueOf();
1600 CHECK_EQ(42.0, the_number);
1601 v8::Handle<v8::Value> new_boxed_number =
1602 v8::NumberObject::New(env->GetIsolate(), 43);
1603 CHECK(new_boxed_number->IsNumberObject());
1604 as_boxed = new_boxed_number.As<v8::NumberObject>();
1605 the_number = as_boxed->ValueOf();
1606 CHECK_EQ(43.0, the_number);
1610 THREADED_TEST(BooleanObject) {
1612 v8::HandleScope scope(env->GetIsolate());
1613 v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
1614 CHECK(boxed_boolean->IsBooleanObject());
1615 v8::Handle<Value> unboxed_boolean = CompileRun("true");
1616 CHECK(!unboxed_boolean->IsBooleanObject());
1617 v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
1618 CHECK(!boxed_not_boolean->IsBooleanObject());
1619 v8::Handle<v8::BooleanObject> as_boxed =
1620 boxed_boolean.As<v8::BooleanObject>();
1621 CHECK(!as_boxed.IsEmpty());
1622 bool the_boolean = as_boxed->ValueOf();
1623 CHECK_EQ(true, the_boolean);
1624 v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
1625 v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
1626 CHECK(boxed_true->IsBooleanObject());
1627 CHECK(boxed_false->IsBooleanObject());
1628 as_boxed = boxed_true.As<v8::BooleanObject>();
1629 CHECK_EQ(true, as_boxed->ValueOf());
1630 as_boxed = boxed_false.As<v8::BooleanObject>();
1631 CHECK_EQ(false, as_boxed->ValueOf());
1635 THREADED_TEST(PrimitiveAndWrappedBooleans) {
1637 v8::HandleScope scope(env->GetIsolate());
1639 Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
1640 CHECK(primitive_false->IsBoolean());
1641 CHECK(!primitive_false->IsBooleanObject());
1642 CHECK(!primitive_false->BooleanValue());
1643 CHECK(!primitive_false->IsTrue());
1644 CHECK(primitive_false->IsFalse());
1646 Local<Value> false_value = BooleanObject::New(false);
1647 CHECK(!false_value->IsBoolean());
1648 CHECK(false_value->IsBooleanObject());
1649 CHECK(false_value->BooleanValue());
1650 CHECK(!false_value->IsTrue());
1651 CHECK(!false_value->IsFalse());
1653 Local<BooleanObject> false_boolean_object = false_value.As<BooleanObject>();
1654 CHECK(!false_boolean_object->IsBoolean());
1655 CHECK(false_boolean_object->IsBooleanObject());
1656 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1657 // CHECK(false_boolean_object->BooleanValue());
1658 CHECK(!false_boolean_object->ValueOf());
1659 CHECK(!false_boolean_object->IsTrue());
1660 CHECK(!false_boolean_object->IsFalse());
1662 Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
1663 CHECK(primitive_true->IsBoolean());
1664 CHECK(!primitive_true->IsBooleanObject());
1665 CHECK(primitive_true->BooleanValue());
1666 CHECK(primitive_true->IsTrue());
1667 CHECK(!primitive_true->IsFalse());
1669 Local<Value> true_value = BooleanObject::New(true);
1670 CHECK(!true_value->IsBoolean());
1671 CHECK(true_value->IsBooleanObject());
1672 CHECK(true_value->BooleanValue());
1673 CHECK(!true_value->IsTrue());
1674 CHECK(!true_value->IsFalse());
1676 Local<BooleanObject> true_boolean_object = true_value.As<BooleanObject>();
1677 CHECK(!true_boolean_object->IsBoolean());
1678 CHECK(true_boolean_object->IsBooleanObject());
1679 // TODO(svenpanne) Uncomment when BooleanObject::BooleanValue() is deleted.
1680 // CHECK(true_boolean_object->BooleanValue());
1681 CHECK(true_boolean_object->ValueOf());
1682 CHECK(!true_boolean_object->IsTrue());
1683 CHECK(!true_boolean_object->IsFalse());
1687 THREADED_TEST(Number) {
1689 v8::HandleScope scope(env->GetIsolate());
1690 double PI = 3.1415926;
1691 Local<v8::Number> pi_obj = v8::Number::New(env->GetIsolate(), PI);
1692 CHECK_EQ(PI, pi_obj->NumberValue());
1696 THREADED_TEST(ToNumber) {
1698 v8::Isolate* isolate = CcTest::isolate();
1699 v8::HandleScope scope(isolate);
1700 Local<String> str = v8_str("3.1415926");
1701 CHECK_EQ(3.1415926, str->NumberValue());
1702 v8::Handle<v8::Boolean> t = v8::True(isolate);
1703 CHECK_EQ(1.0, t->NumberValue());
1704 v8::Handle<v8::Boolean> f = v8::False(isolate);
1705 CHECK_EQ(0.0, f->NumberValue());
1709 THREADED_TEST(Date) {
1711 v8::HandleScope scope(env->GetIsolate());
1712 double PI = 3.1415926;
1713 Local<Value> date = v8::Date::New(env->GetIsolate(), PI);
1714 CHECK_EQ(3.0, date->NumberValue());
1715 date.As<v8::Date>()->Set(v8_str("property"),
1716 v8::Integer::New(env->GetIsolate(), 42));
1717 CHECK_EQ(42, date.As<v8::Date>()->Get(v8_str("property"))->Int32Value());
1721 THREADED_TEST(Boolean) {
1723 v8::Isolate* isolate = env->GetIsolate();
1724 v8::HandleScope scope(isolate);
1725 v8::Handle<v8::Boolean> t = v8::True(isolate);
1727 v8::Handle<v8::Boolean> f = v8::False(isolate);
1729 v8::Handle<v8::Primitive> u = v8::Undefined(isolate);
1730 CHECK(!u->BooleanValue());
1731 v8::Handle<v8::Primitive> n = v8::Null(isolate);
1732 CHECK(!n->BooleanValue());
1733 v8::Handle<String> str1 = v8_str("");
1734 CHECK(!str1->BooleanValue());
1735 v8::Handle<String> str2 = v8_str("x");
1736 CHECK(str2->BooleanValue());
1737 CHECK(!v8::Number::New(isolate, 0)->BooleanValue());
1738 CHECK(v8::Number::New(isolate, -1)->BooleanValue());
1739 CHECK(v8::Number::New(isolate, 1)->BooleanValue());
1740 CHECK(v8::Number::New(isolate, 42)->BooleanValue());
1741 CHECK(!v8_compile("NaN")->Run()->BooleanValue());
1745 static void DummyCallHandler(const v8::FunctionCallbackInfo<v8::Value>& args) {
1746 ApiTestFuzzer::Fuzz();
1747 args.GetReturnValue().Set(v8_num(13.4));
1751 static void GetM(Local<String> name,
1752 const v8::PropertyCallbackInfo<v8::Value>& info) {
1753 ApiTestFuzzer::Fuzz();
1754 info.GetReturnValue().Set(v8_num(876));
1758 THREADED_TEST(GlobalPrototype) {
1759 v8::Isolate* isolate = CcTest::isolate();
1760 v8::HandleScope scope(isolate);
1761 v8::Handle<v8::FunctionTemplate> func_templ =
1762 v8::FunctionTemplate::New(isolate);
1763 func_templ->PrototypeTemplate()->Set(
1764 isolate, "dummy", v8::FunctionTemplate::New(isolate, DummyCallHandler));
1765 v8::Handle<ObjectTemplate> templ = func_templ->InstanceTemplate();
1766 templ->Set(isolate, "x", v8_num(200));
1767 templ->SetAccessor(v8_str("m"), GetM);
1768 LocalContext env(0, templ);
1769 v8::Handle<Script> script(v8_compile("dummy()"));
1770 v8::Handle<Value> result(script->Run());
1771 CHECK_EQ(13.4, result->NumberValue());
1772 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value());
1773 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value());
1777 THREADED_TEST(ObjectTemplate) {
1778 v8::Isolate* isolate = CcTest::isolate();
1779 v8::HandleScope scope(isolate);
1780 Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
1781 v8::Local<v8::String> class_name =
1782 v8::String::NewFromUtf8(isolate, "the_class_name");
1783 fun->SetClassName(class_name);
1784 Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun);
1785 templ1->Set(isolate, "x", v8_num(10));
1786 templ1->Set(isolate, "y", v8_num(13));
1788 Local<v8::Object> instance1 = templ1->NewInstance();
1789 CHECK(class_name->StrictEquals(instance1->GetConstructorName()));
1790 env->Global()->Set(v8_str("p"), instance1);
1791 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue());
1792 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue());
1793 Local<v8::FunctionTemplate> fun2 = v8::FunctionTemplate::New(isolate);
1794 fun2->PrototypeTemplate()->Set(isolate, "nirk", v8_num(123));
1795 Local<ObjectTemplate> templ2 = fun2->InstanceTemplate();
1796 templ2->Set(isolate, "a", v8_num(12));
1797 templ2->Set(isolate, "b", templ1);
1798 Local<v8::Object> instance2 = templ2->NewInstance();
1799 env->Global()->Set(v8_str("q"), instance2);
1800 CHECK(v8_compile("(q.nirk == 123)")->Run()->BooleanValue());
1801 CHECK(v8_compile("(q.a == 12)")->Run()->BooleanValue());
1802 CHECK(v8_compile("(q.b.x == 10)")->Run()->BooleanValue());
1803 CHECK(v8_compile("(q.b.y == 13)")->Run()->BooleanValue());
1807 static void GetFlabby(const v8::FunctionCallbackInfo<v8::Value>& args) {
1808 ApiTestFuzzer::Fuzz();
1809 args.GetReturnValue().Set(v8_num(17.2));
1813 static void GetKnurd(Local<String> property,
1814 const v8::PropertyCallbackInfo<v8::Value>& info) {
1815 ApiTestFuzzer::Fuzz();
1816 info.GetReturnValue().Set(v8_num(15.2));
1820 THREADED_TEST(DescriptorInheritance) {
1821 v8::Isolate* isolate = CcTest::isolate();
1822 v8::HandleScope scope(isolate);
1823 v8::Handle<v8::FunctionTemplate> super = v8::FunctionTemplate::New(isolate);
1824 super->PrototypeTemplate()->Set(isolate, "flabby",
1825 v8::FunctionTemplate::New(isolate,
1827 super->PrototypeTemplate()->Set(isolate, "PI", v8_num(3.14));
1829 super->InstanceTemplate()->SetAccessor(v8_str("knurd"), GetKnurd);
1831 v8::Handle<v8::FunctionTemplate> base1 = v8::FunctionTemplate::New(isolate);
1832 base1->Inherit(super);
1833 base1->PrototypeTemplate()->Set(isolate, "v1", v8_num(20.1));
1835 v8::Handle<v8::FunctionTemplate> base2 = v8::FunctionTemplate::New(isolate);
1836 base2->Inherit(super);
1837 base2->PrototypeTemplate()->Set(isolate, "v2", v8_num(10.1));
1841 env->Global()->Set(v8_str("s"), super->GetFunction());
1842 env->Global()->Set(v8_str("base1"), base1->GetFunction());
1843 env->Global()->Set(v8_str("base2"), base2->GetFunction());
1845 // Checks right __proto__ chain.
1846 CHECK(CompileRun("base1.prototype.__proto__ == s.prototype")->BooleanValue());
1847 CHECK(CompileRun("base2.prototype.__proto__ == s.prototype")->BooleanValue());
1849 CHECK(v8_compile("s.prototype.PI == 3.14")->Run()->BooleanValue());
1851 // Instance accessor should not be visible on function object or its prototype
1852 CHECK(CompileRun("s.knurd == undefined")->BooleanValue());
1853 CHECK(CompileRun("s.prototype.knurd == undefined")->BooleanValue());
1854 CHECK(CompileRun("base1.prototype.knurd == undefined")->BooleanValue());
1856 env->Global()->Set(v8_str("obj"),
1857 base1->GetFunction()->NewInstance());
1858 CHECK_EQ(17.2, v8_compile("obj.flabby()")->Run()->NumberValue());
1859 CHECK(v8_compile("'flabby' in obj")->Run()->BooleanValue());
1860 CHECK_EQ(15.2, v8_compile("obj.knurd")->Run()->NumberValue());
1861 CHECK(v8_compile("'knurd' in obj")->Run()->BooleanValue());
1862 CHECK_EQ(20.1, v8_compile("obj.v1")->Run()->NumberValue());
1864 env->Global()->Set(v8_str("obj2"),
1865 base2->GetFunction()->NewInstance());
1866 CHECK_EQ(17.2, v8_compile("obj2.flabby()")->Run()->NumberValue());
1867 CHECK(v8_compile("'flabby' in obj2")->Run()->BooleanValue());
1868 CHECK_EQ(15.2, v8_compile("obj2.knurd")->Run()->NumberValue());
1869 CHECK(v8_compile("'knurd' in obj2")->Run()->BooleanValue());
1870 CHECK_EQ(10.1, v8_compile("obj2.v2")->Run()->NumberValue());
1872 // base1 and base2 cannot cross reference to each's prototype
1873 CHECK(v8_compile("obj.v2")->Run()->IsUndefined());
1874 CHECK(v8_compile("obj2.v1")->Run()->IsUndefined());
1878 // Helper functions for Interceptor/Accessor interaction tests
1880 void SimpleAccessorGetter(Local<String> name,
1881 const v8::PropertyCallbackInfo<v8::Value>& info) {
1882 Handle<Object> self = Handle<Object>::Cast(info.This());
1883 info.GetReturnValue().Set(
1884 self->Get(String::Concat(v8_str("accessor_"), name)));
1887 void SimpleAccessorSetter(Local<String> name, Local<Value> value,
1888 const v8::PropertyCallbackInfo<void>& info) {
1889 Handle<Object> self = Handle<Object>::Cast(info.This());
1890 self->Set(String::Concat(v8_str("accessor_"), name), value);
1893 void SymbolAccessorGetter(Local<Name> name,
1894 const v8::PropertyCallbackInfo<v8::Value>& info) {
1895 CHECK(name->IsSymbol());
1896 Local<Symbol> sym = Local<Symbol>::Cast(name);
1897 if (sym->Name()->IsUndefined())
1899 SimpleAccessorGetter(Local<String>::Cast(sym->Name()), info);
1902 void SymbolAccessorSetter(Local<Name> name, Local<Value> value,
1903 const v8::PropertyCallbackInfo<void>& info) {
1904 CHECK(name->IsSymbol());
1905 Local<Symbol> sym = Local<Symbol>::Cast(name);
1906 if (sym->Name()->IsUndefined())
1908 SimpleAccessorSetter(Local<String>::Cast(sym->Name()), value, info);
1911 void SymbolAccessorGetterReturnsDefault(
1912 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1913 CHECK(name->IsSymbol());
1914 Local<Symbol> sym = Local<Symbol>::Cast(name);
1915 if (sym->Name()->IsUndefined()) return;
1916 info.GetReturnValue().Set(info.Data());
1919 static void ThrowingSymbolAccessorGetter(
1920 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
1921 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(name));
1925 THREADED_TEST(ExecutableAccessorIsPreservedOnAttributeChange) {
1926 v8::Isolate* isolate = CcTest::isolate();
1927 v8::HandleScope scope(isolate);
1929 v8::Local<v8::Value> res = CompileRun("var a = []; a;");
1930 i::Handle<i::JSObject> a(v8::Utils::OpenHandle(v8::Object::Cast(*res)));
1931 CHECK(a->map()->instance_descriptors()->IsFixedArray());
1932 CHECK_GT(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1933 CompileRun("Object.defineProperty(a, 'length', { writable: false });");
1934 CHECK_EQ(i::FixedArray::cast(a->map()->instance_descriptors())->length(), 0);
1935 // But we should still have an ExecutableAccessorInfo.
1936 i::Handle<i::String> name(v8::Utils::OpenHandle(*v8_str("length")));
1937 i::LookupIterator it(a, name, i::LookupIterator::OWN_SKIP_INTERCEPTOR);
1938 CHECK_EQ(i::LookupIterator::ACCESSOR, it.state());
1939 CHECK(it.GetAccessors()->IsExecutableAccessorInfo());
1943 THREADED_TEST(UndefinedIsNotEnumerable) {
1945 v8::HandleScope scope(env->GetIsolate());
1946 v8::Handle<Value> result = CompileRun("this.propertyIsEnumerable(undefined)");
1947 CHECK(result->IsFalse());
1951 v8::Handle<Script> call_recursively_script;
1952 static const int kTargetRecursionDepth = 150; // near maximum
1955 static void CallScriptRecursivelyCall(
1956 const v8::FunctionCallbackInfo<v8::Value>& args) {
1957 ApiTestFuzzer::Fuzz();
1958 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1959 if (depth == kTargetRecursionDepth) return;
1960 args.This()->Set(v8_str("depth"),
1961 v8::Integer::New(args.GetIsolate(), depth + 1));
1962 args.GetReturnValue().Set(call_recursively_script->Run());
1966 static void CallFunctionRecursivelyCall(
1967 const v8::FunctionCallbackInfo<v8::Value>& args) {
1968 ApiTestFuzzer::Fuzz();
1969 int depth = args.This()->Get(v8_str("depth"))->Int32Value();
1970 if (depth == kTargetRecursionDepth) {
1971 printf("[depth = %d]\n", depth);
1974 args.This()->Set(v8_str("depth"),
1975 v8::Integer::New(args.GetIsolate(), depth + 1));
1976 v8::Handle<Value> function =
1977 args.This()->Get(v8_str("callFunctionRecursively"));
1978 args.GetReturnValue().Set(
1979 function.As<Function>()->Call(args.This(), 0, NULL));
1983 THREADED_TEST(DeepCrossLanguageRecursion) {
1984 v8::Isolate* isolate = CcTest::isolate();
1985 v8::HandleScope scope(isolate);
1986 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
1987 global->Set(v8_str("callScriptRecursively"),
1988 v8::FunctionTemplate::New(isolate, CallScriptRecursivelyCall));
1989 global->Set(v8_str("callFunctionRecursively"),
1990 v8::FunctionTemplate::New(isolate, CallFunctionRecursivelyCall));
1991 LocalContext env(NULL, global);
1993 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
1994 call_recursively_script = v8_compile("callScriptRecursively()");
1995 call_recursively_script->Run();
1996 call_recursively_script = v8::Handle<Script>();
1998 env->Global()->Set(v8_str("depth"), v8::Integer::New(isolate, 0));
1999 CompileRun("callFunctionRecursively()");
2003 static void ThrowingPropertyHandlerGet(
2004 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>& info) {
2005 // Since this interceptor is used on "with" objects, the runtime will look up
2006 // @@unscopables. Punt.
2007 if (key->IsSymbol()) return;
2008 ApiTestFuzzer::Fuzz();
2009 info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
2013 static void ThrowingPropertyHandlerSet(
2014 Local<Name> key, Local<Value>,
2015 const v8::PropertyCallbackInfo<v8::Value>& info) {
2016 info.GetIsolate()->ThrowException(key);
2017 info.GetReturnValue().SetUndefined(); // not the same as empty handle
2021 THREADED_TEST(CallbackExceptionRegression) {
2022 v8::Isolate* isolate = CcTest::isolate();
2023 v8::HandleScope scope(isolate);
2024 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
2025 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(
2026 ThrowingPropertyHandlerGet, ThrowingPropertyHandlerSet));
2028 env->Global()->Set(v8_str("obj"), obj->NewInstance());
2029 v8::Handle<Value> otto =
2030 CompileRun("try { with (obj) { otto; } } catch (e) { e; }");
2031 CHECK(v8_str("otto")->Equals(otto));
2032 v8::Handle<Value> netto =
2033 CompileRun("try { with (obj) { netto = 4; } } catch (e) { e; }");
2034 CHECK(v8_str("netto")->Equals(netto));
2038 THREADED_TEST(FunctionPrototype) {
2039 v8::Isolate* isolate = CcTest::isolate();
2040 v8::HandleScope scope(isolate);
2041 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(isolate);
2042 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321));
2044 env->Global()->Set(v8_str("Foo"), Foo->GetFunction());
2045 Local<Script> script = v8_compile("Foo.prototype.plak");
2046 CHECK_EQ(script->Run()->Int32Value(), 321);
2050 THREADED_TEST(InternalFields) {
2052 v8::Isolate* isolate = env->GetIsolate();
2053 v8::HandleScope scope(isolate);
2055 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2056 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2057 instance_templ->SetInternalFieldCount(1);
2058 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2059 CHECK_EQ(1, obj->InternalFieldCount());
2060 CHECK(obj->GetInternalField(0)->IsUndefined());
2061 obj->SetInternalField(0, v8_num(17));
2062 CHECK_EQ(17, obj->GetInternalField(0)->Int32Value());
2066 THREADED_TEST(GlobalObjectInternalFields) {
2067 v8::Isolate* isolate = CcTest::isolate();
2068 v8::HandleScope scope(isolate);
2069 Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
2070 global_template->SetInternalFieldCount(1);
2071 LocalContext env(NULL, global_template);
2072 v8::Handle<v8::Object> global_proxy = env->Global();
2073 v8::Handle<v8::Object> global = global_proxy->GetPrototype().As<v8::Object>();
2074 CHECK_EQ(1, global->InternalFieldCount());
2075 CHECK(global->GetInternalField(0)->IsUndefined());
2076 global->SetInternalField(0, v8_num(17));
2077 CHECK_EQ(17, global->GetInternalField(0)->Int32Value());
2081 THREADED_TEST(GlobalObjectHasRealIndexedProperty) {
2083 v8::HandleScope scope(CcTest::isolate());
2085 v8::Local<v8::Object> global = env->Global();
2086 global->Set(0, v8::String::NewFromUtf8(CcTest::isolate(), "value"));
2087 CHECK(global->HasRealIndexedProperty(0));
2091 static void CheckAlignedPointerInInternalField(Handle<v8::Object> obj,
2093 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2094 obj->SetAlignedPointerInInternalField(0, value);
2095 CcTest::heap()->CollectAllGarbage();
2096 CHECK_EQ(value, obj->GetAlignedPointerFromInternalField(0));
2100 THREADED_TEST(InternalFieldsAlignedPointers) {
2102 v8::Isolate* isolate = env->GetIsolate();
2103 v8::HandleScope scope(isolate);
2105 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
2106 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
2107 instance_templ->SetInternalFieldCount(1);
2108 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
2109 CHECK_EQ(1, obj->InternalFieldCount());
2111 CheckAlignedPointerInInternalField(obj, NULL);
2113 int* heap_allocated = new int[100];
2114 CheckAlignedPointerInInternalField(obj, heap_allocated);
2115 delete[] heap_allocated;
2117 int stack_allocated[100];
2118 CheckAlignedPointerInInternalField(obj, stack_allocated);
2120 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2121 CheckAlignedPointerInInternalField(obj, huge);
2123 v8::Global<v8::Object> persistent(isolate, obj);
2124 CHECK_EQ(1, Object::InternalFieldCount(persistent));
2125 CHECK_EQ(huge, Object::GetAlignedPointerFromInternalField(persistent, 0));
2129 static void CheckAlignedPointerInEmbedderData(LocalContext* env, int index,
2131 CHECK_EQ(0, static_cast<int>(reinterpret_cast<uintptr_t>(value) & 0x1));
2132 (*env)->SetAlignedPointerInEmbedderData(index, value);
2133 CcTest::heap()->CollectAllGarbage();
2134 CHECK_EQ(value, (*env)->GetAlignedPointerFromEmbedderData(index));
2138 static void* AlignedTestPointer(int i) {
2139 return reinterpret_cast<void*>(i * 1234);
2143 THREADED_TEST(EmbedderDataAlignedPointers) {
2145 v8::HandleScope scope(env->GetIsolate());
2147 CheckAlignedPointerInEmbedderData(&env, 0, NULL);
2149 int* heap_allocated = new int[100];
2150 CheckAlignedPointerInEmbedderData(&env, 1, heap_allocated);
2151 delete[] heap_allocated;
2153 int stack_allocated[100];
2154 CheckAlignedPointerInEmbedderData(&env, 2, stack_allocated);
2156 void* huge = reinterpret_cast<void*>(~static_cast<uintptr_t>(1));
2157 CheckAlignedPointerInEmbedderData(&env, 3, huge);
2159 // Test growing of the embedder data's backing store.
2160 for (int i = 0; i < 100; i++) {
2161 env->SetAlignedPointerInEmbedderData(i, AlignedTestPointer(i));
2163 CcTest::heap()->CollectAllGarbage();
2164 for (int i = 0; i < 100; i++) {
2165 CHECK_EQ(AlignedTestPointer(i), env->GetAlignedPointerFromEmbedderData(i));
2170 static void CheckEmbedderData(LocalContext* env, int index,
2171 v8::Handle<Value> data) {
2172 (*env)->SetEmbedderData(index, data);
2173 CHECK((*env)->GetEmbedderData(index)->StrictEquals(data));
2177 THREADED_TEST(EmbedderData) {
2179 v8::Isolate* isolate = env->GetIsolate();
2180 v8::HandleScope scope(isolate);
2183 &env, 3, v8::String::NewFromUtf8(isolate, "The quick brown fox jumps"));
2184 CheckEmbedderData(&env, 2,
2185 v8::String::NewFromUtf8(isolate, "over the lazy dog."));
2186 CheckEmbedderData(&env, 1, v8::Number::New(isolate, 1.2345));
2187 CheckEmbedderData(&env, 0, v8::Boolean::New(isolate, true));
2191 THREADED_TEST(GetIsolate) {
2193 v8::Isolate* isolate = env->GetIsolate();
2194 v8::HandleScope scope(isolate);
2195 Local<v8::Object> obj = v8::Object::New(isolate);
2196 CHECK_EQ(isolate, obj->GetIsolate());
2197 CHECK_EQ(isolate, CcTest::global()->GetIsolate());
2201 THREADED_TEST(IdentityHash) {
2203 v8::Isolate* isolate = env->GetIsolate();
2204 v8::HandleScope scope(isolate);
2206 // Ensure that the test starts with an fresh heap to test whether the hash
2207 // code is based on the address.
2208 CcTest::heap()->CollectAllGarbage();
2209 Local<v8::Object> obj = v8::Object::New(isolate);
2210 int hash = obj->GetIdentityHash();
2211 int hash1 = obj->GetIdentityHash();
2212 CHECK_EQ(hash, hash1);
2213 int hash2 = v8::Object::New(isolate)->GetIdentityHash();
2214 // Since the identity hash is essentially a random number two consecutive
2215 // objects should not be assigned the same hash code. If the test below fails
2216 // the random number generator should be evaluated.
2217 CHECK_NE(hash, hash2);
2218 CcTest::heap()->CollectAllGarbage();
2219 int hash3 = v8::Object::New(isolate)->GetIdentityHash();
2220 // Make sure that the identity hash is not based on the initial address of
2221 // the object alone. If the test below fails the random number generator
2222 // should be evaluated.
2223 CHECK_NE(hash, hash3);
2224 int hash4 = obj->GetIdentityHash();
2225 CHECK_EQ(hash, hash4);
2227 // Check identity hashes behaviour in the presence of JS accessors.
2228 // Put a getter for 'v8::IdentityHash' on the Object's prototype:
2230 CompileRun("Object.prototype['v8::IdentityHash'] = 42;\n");
2231 Local<v8::Object> o1 = v8::Object::New(isolate);
2232 Local<v8::Object> o2 = v8::Object::New(isolate);
2233 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2237 "function cnst() { return 42; };\n"
2238 "Object.prototype.__defineGetter__('v8::IdentityHash', cnst);\n");
2239 Local<v8::Object> o1 = v8::Object::New(isolate);
2240 Local<v8::Object> o2 = v8::Object::New(isolate);
2241 CHECK_NE(o1->GetIdentityHash(), o2->GetIdentityHash());
2246 void GlobalProxyIdentityHash(bool set_in_js) {
2248 v8::Isolate* isolate = env->GetIsolate();
2249 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2250 v8::HandleScope scope(isolate);
2251 Handle<Object> global_proxy = env->Global();
2252 i::Handle<i::Object> i_global_proxy = v8::Utils::OpenHandle(*global_proxy);
2253 env->Global()->Set(v8_str("global"), global_proxy);
2254 i::Handle<i::Object> original_hash;
2256 CompileRun("var m = new Set(); m.add(global);");
2257 original_hash = i::Handle<i::Object>(i_global_proxy->GetHash(), i_isolate);
2259 original_hash = i::Handle<i::Object>(
2260 i::Object::GetOrCreateHash(i_isolate, i_global_proxy));
2262 CHECK(original_hash->IsSmi());
2263 int32_t hash1 = i::Handle<i::Smi>::cast(original_hash)->value();
2264 // Hash should be retained after being detached.
2265 env->DetachGlobal();
2266 int hash2 = global_proxy->GetIdentityHash();
2267 CHECK_EQ(hash1, hash2);
2269 // Re-attach global proxy to a new context, hash should stay the same.
2270 LocalContext env2(NULL, Handle<ObjectTemplate>(), global_proxy);
2271 int hash3 = global_proxy->GetIdentityHash();
2272 CHECK_EQ(hash1, hash3);
2277 THREADED_TEST(GlobalProxyIdentityHash) {
2278 GlobalProxyIdentityHash(true);
2279 GlobalProxyIdentityHash(false);
2283 TEST(SymbolIdentityHash) {
2285 v8::Isolate* isolate = env->GetIsolate();
2286 v8::HandleScope scope(isolate);
2289 Local<v8::Symbol> symbol = v8::Symbol::New(isolate);
2290 int hash = symbol->GetIdentityHash();
2291 int hash1 = symbol->GetIdentityHash();
2292 CHECK_EQ(hash, hash1);
2293 CcTest::heap()->CollectAllGarbage();
2294 int hash3 = symbol->GetIdentityHash();
2295 CHECK_EQ(hash, hash3);
2299 v8::Handle<v8::Symbol> js_symbol =
2300 CompileRun("Symbol('foo')").As<v8::Symbol>();
2301 int hash = js_symbol->GetIdentityHash();
2302 int hash1 = js_symbol->GetIdentityHash();
2303 CHECK_EQ(hash, hash1);
2304 CcTest::heap()->CollectAllGarbage();
2305 int hash3 = js_symbol->GetIdentityHash();
2306 CHECK_EQ(hash, hash3);
2311 TEST(StringIdentityHash) {
2313 v8::Isolate* isolate = env->GetIsolate();
2314 v8::HandleScope scope(isolate);
2316 Local<v8::String> str = v8::String::NewFromUtf8(isolate, "str1");
2317 int hash = str->GetIdentityHash();
2318 int hash1 = str->GetIdentityHash();
2319 CHECK_EQ(hash, hash1);
2320 CcTest::heap()->CollectAllGarbage();
2321 int hash3 = str->GetIdentityHash();
2322 CHECK_EQ(hash, hash3);
2324 Local<v8::String> str2 = v8::String::NewFromUtf8(isolate, "str1");
2325 int hash4 = str2->GetIdentityHash();
2326 CHECK_EQ(hash, hash4);
2330 THREADED_TEST(SymbolProperties) {
2332 v8::Isolate* isolate = env->GetIsolate();
2333 v8::HandleScope scope(isolate);
2335 v8::Local<v8::Object> obj = v8::Object::New(isolate);
2336 v8::Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
2337 v8::Local<v8::Symbol> sym2 = v8::Symbol::New(isolate, v8_str("my-symbol"));
2338 v8::Local<v8::Symbol> sym3 = v8::Symbol::New(isolate, v8_str("sym3"));
2340 CcTest::heap()->CollectAllGarbage();
2342 // Check basic symbol functionality.
2343 CHECK(sym1->IsSymbol());
2344 CHECK(sym2->IsSymbol());
2345 CHECK(!obj->IsSymbol());
2347 CHECK(sym1->Equals(sym1));
2348 CHECK(sym2->Equals(sym2));
2349 CHECK(!sym1->Equals(sym2));
2350 CHECK(!sym2->Equals(sym1));
2351 CHECK(sym1->StrictEquals(sym1));
2352 CHECK(sym2->StrictEquals(sym2));
2353 CHECK(!sym1->StrictEquals(sym2));
2354 CHECK(!sym2->StrictEquals(sym1));
2356 CHECK(sym2->Name()->Equals(v8_str("my-symbol")));
2358 v8::Local<v8::Value> sym_val = sym2;
2359 CHECK(sym_val->IsSymbol());
2360 CHECK(sym_val->Equals(sym2));
2361 CHECK(sym_val->StrictEquals(sym2));
2362 CHECK(v8::Symbol::Cast(*sym_val)->Equals(sym2));
2364 v8::Local<v8::Value> sym_obj = v8::SymbolObject::New(isolate, sym2);
2365 CHECK(sym_obj->IsSymbolObject());
2366 CHECK(!sym2->IsSymbolObject());
2367 CHECK(!obj->IsSymbolObject());
2368 CHECK(!sym_obj->Equals(sym2));
2369 CHECK(!sym_obj->StrictEquals(sym2));
2370 CHECK(v8::SymbolObject::Cast(*sym_obj)->Equals(sym_obj));
2371 CHECK(v8::SymbolObject::Cast(*sym_obj)->ValueOf()->Equals(sym2));
2373 // Make sure delete of a non-existent symbol property works.
2374 CHECK(obj->Delete(sym1));
2375 CHECK(!obj->Has(sym1));
2377 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 1503)));
2378 CHECK(obj->Has(sym1));
2379 CHECK_EQ(1503, obj->Get(sym1)->Int32Value());
2380 CHECK(obj->Set(sym1, v8::Integer::New(isolate, 2002)));
2381 CHECK(obj->Has(sym1));
2382 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2383 CHECK_EQ(v8::None, obj->GetPropertyAttributes(sym1));
2385 CHECK_EQ(0u, obj->GetOwnPropertyNames()->Length());
2386 unsigned num_props = obj->GetPropertyNames()->Length();
2387 CHECK(obj->Set(v8::String::NewFromUtf8(isolate, "bla"),
2388 v8::Integer::New(isolate, 20)));
2389 CHECK_EQ(1u, obj->GetOwnPropertyNames()->Length());
2390 CHECK_EQ(num_props + 1, obj->GetPropertyNames()->Length());
2392 CcTest::heap()->CollectAllGarbage();
2394 CHECK(obj->SetAccessor(sym3, SymbolAccessorGetter, SymbolAccessorSetter));
2395 CHECK(obj->Get(sym3)->IsUndefined());
2396 CHECK(obj->Set(sym3, v8::Integer::New(isolate, 42)));
2397 CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2398 CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2399 ->Equals(v8::Integer::New(isolate, 42)));
2401 // Add another property and delete it afterwards to force the object in
2403 CHECK(obj->Set(sym2, v8::Integer::New(isolate, 2008)));
2404 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2405 CHECK_EQ(2008, obj->Get(sym2)->Int32Value());
2406 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2407 CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2409 CHECK(obj->Has(sym1));
2410 CHECK(obj->Has(sym2));
2411 CHECK(obj->Has(sym3));
2412 CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2413 CHECK(obj->Delete(sym2));
2414 CHECK(obj->Has(sym1));
2415 CHECK(!obj->Has(sym2));
2416 CHECK(obj->Has(sym3));
2417 CHECK(obj->Has(v8::String::NewFromUtf8(isolate, "accessor_sym3")));
2418 CHECK_EQ(2002, obj->Get(sym1)->Int32Value());
2419 CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2420 CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2421 ->Equals(v8::Integer::New(isolate, 42)));
2422 CHECK_EQ(2u, obj->GetOwnPropertyNames()->Length());
2424 // Symbol properties are inherited.
2425 v8::Local<v8::Object> child = v8::Object::New(isolate);
2426 child->SetPrototype(obj);
2427 CHECK(child->Has(sym1));
2428 CHECK_EQ(2002, child->Get(sym1)->Int32Value());
2429 CHECK(obj->Get(sym3)->Equals(v8::Integer::New(isolate, 42)));
2430 CHECK(obj->Get(v8::String::NewFromUtf8(isolate, "accessor_sym3"))
2431 ->Equals(v8::Integer::New(isolate, 42)));
2432 CHECK_EQ(0u, child->GetOwnPropertyNames()->Length());
2436 THREADED_TEST(SymbolTemplateProperties) {
2438 v8::Isolate* isolate = env->GetIsolate();
2439 v8::HandleScope scope(isolate);
2440 v8::Local<v8::FunctionTemplate> foo = v8::FunctionTemplate::New(isolate);
2441 v8::Local<v8::Name> name = v8::Symbol::New(isolate);
2442 CHECK(!name.IsEmpty());
2443 foo->PrototypeTemplate()->Set(name, v8::FunctionTemplate::New(isolate));
2444 v8::Local<v8::Object> new_instance = foo->InstanceTemplate()->NewInstance();
2445 CHECK(!new_instance.IsEmpty());
2446 CHECK(new_instance->Has(name));
2450 THREADED_TEST(GlobalSymbols) {
2452 v8::Isolate* isolate = env->GetIsolate();
2453 v8::HandleScope scope(isolate);
2455 v8::Local<String> name = v8_str("my-symbol");
2456 v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name);
2457 v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name);
2458 CHECK(glob2->SameValue(glob));
2460 v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name);
2461 v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name);
2462 CHECK(glob_api2->SameValue(glob_api));
2463 CHECK(!glob_api->SameValue(glob));
2465 v8::Local<v8::Symbol> sym = v8::Symbol::New(isolate, name);
2466 CHECK(!sym->SameValue(glob));
2468 CompileRun("var sym2 = Symbol.for('my-symbol')");
2469 v8::Local<Value> sym2 = env->Global()->Get(v8_str("sym2"));
2470 CHECK(sym2->SameValue(glob));
2471 CHECK(!sym2->SameValue(glob_api));
2475 static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
2478 v8::Isolate* isolate = env->GetIsolate();
2479 v8::HandleScope scope(isolate);
2481 v8::Local<v8::Symbol> symbol = getter(isolate);
2482 std::string script = std::string("var sym = ") + name;
2483 CompileRun(script.c_str());
2484 v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
2486 CHECK(!value.IsEmpty());
2487 CHECK(!symbol.IsEmpty());
2488 CHECK(value->SameValue(symbol));
2492 THREADED_TEST(WellKnownSymbols) {
2493 CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
2494 CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
2498 class ScopedArrayBufferContents {
2500 explicit ScopedArrayBufferContents(const v8::ArrayBuffer::Contents& contents)
2501 : contents_(contents) {}
2502 ~ScopedArrayBufferContents() { free(contents_.Data()); }
2503 void* Data() const { return contents_.Data(); }
2504 size_t ByteLength() const { return contents_.ByteLength(); }
2507 const v8::ArrayBuffer::Contents contents_;
2510 template <typename T>
2511 static void CheckInternalFieldsAreZero(v8::Handle<T> value) {
2512 CHECK_EQ(T::kInternalFieldCount, value->InternalFieldCount());
2513 for (int i = 0; i < value->InternalFieldCount(); i++) {
2514 CHECK_EQ(0, value->GetInternalField(i)->Int32Value());
2519 THREADED_TEST(ArrayBuffer_ApiInternalToExternal) {
2521 v8::Isolate* isolate = env->GetIsolate();
2522 v8::HandleScope handle_scope(isolate);
2524 Local<v8::ArrayBuffer> ab = v8::ArrayBuffer::New(isolate, 1024);
2525 CheckInternalFieldsAreZero(ab);
2526 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2527 CHECK(!ab->IsExternal());
2528 CcTest::heap()->CollectAllGarbage();
2530 ScopedArrayBufferContents ab_contents(ab->Externalize());
2531 CHECK(ab->IsExternal());
2533 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2534 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2535 DCHECK(data != NULL);
2536 env->Global()->Set(v8_str("ab"), ab);
2538 v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2539 CHECK_EQ(1024, result->Int32Value());
2541 result = CompileRun(
2542 "var u8 = new Uint8Array(ab);"
2546 CHECK_EQ(1024, result->Int32Value());
2547 CHECK_EQ(0xFF, data[0]);
2548 CHECK_EQ(0xAA, data[1]);
2551 result = CompileRun("u8[0] + u8[1]");
2552 CHECK_EQ(0xDD, result->Int32Value());
2556 THREADED_TEST(ArrayBuffer_JSInternalToExternal) {
2558 v8::Isolate* isolate = env->GetIsolate();
2559 v8::HandleScope handle_scope(isolate);
2562 v8::Local<v8::Value> result = CompileRun(
2563 "var ab1 = new ArrayBuffer(2);"
2564 "var u8_a = new Uint8Array(ab1);"
2566 "u8_a[1] = 0xFF; u8_a.buffer");
2567 Local<v8::ArrayBuffer> ab1 = Local<v8::ArrayBuffer>::Cast(result);
2568 CheckInternalFieldsAreZero(ab1);
2569 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2570 CHECK(!ab1->IsExternal());
2571 ScopedArrayBufferContents ab1_contents(ab1->Externalize());
2572 CHECK(ab1->IsExternal());
2574 result = CompileRun("ab1.byteLength");
2575 CHECK_EQ(2, result->Int32Value());
2576 result = CompileRun("u8_a[0]");
2577 CHECK_EQ(0xAA, result->Int32Value());
2578 result = CompileRun("u8_a[1]");
2579 CHECK_EQ(0xFF, result->Int32Value());
2580 result = CompileRun(
2581 "var u8_b = new Uint8Array(ab1);"
2584 CHECK_EQ(0xBB, result->Int32Value());
2585 result = CompileRun("u8_b[1]");
2586 CHECK_EQ(0xFF, result->Int32Value());
2588 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2589 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2590 CHECK_EQ(0xBB, ab1_data[0]);
2591 CHECK_EQ(0xFF, ab1_data[1]);
2594 result = CompileRun("u8_a[0] + u8_a[1]");
2595 CHECK_EQ(0xDD, result->Int32Value());
2599 THREADED_TEST(ArrayBuffer_External) {
2601 v8::Isolate* isolate = env->GetIsolate();
2602 v8::HandleScope handle_scope(isolate);
2604 i::ScopedVector<uint8_t> my_data(100);
2605 memset(my_data.start(), 0, 100);
2606 Local<v8::ArrayBuffer> ab3 =
2607 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2608 CheckInternalFieldsAreZero(ab3);
2609 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2610 CHECK(ab3->IsExternal());
2612 env->Global()->Set(v8_str("ab3"), ab3);
2614 v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2615 CHECK_EQ(100, result->Int32Value());
2617 result = CompileRun(
2618 "var u8_b = new Uint8Array(ab3);"
2622 CHECK_EQ(100, result->Int32Value());
2623 CHECK_EQ(0xBB, my_data[0]);
2624 CHECK_EQ(0xCC, my_data[1]);
2627 result = CompileRun("u8_b[0] + u8_b[1]");
2628 CHECK_EQ(0xDD, result->Int32Value());
2632 THREADED_TEST(ArrayBuffer_DisableNeuter) {
2634 v8::Isolate* isolate = env->GetIsolate();
2635 v8::HandleScope handle_scope(isolate);
2637 i::ScopedVector<uint8_t> my_data(100);
2638 memset(my_data.start(), 0, 100);
2639 Local<v8::ArrayBuffer> ab =
2640 v8::ArrayBuffer::New(isolate, my_data.start(), 100);
2641 CHECK(ab->IsNeuterable());
2643 i::Handle<i::JSArrayBuffer> buf = v8::Utils::OpenHandle(*ab);
2644 buf->set_is_neuterable(false);
2646 CHECK(!ab->IsNeuterable());
2650 static void CheckDataViewIsNeutered(v8::Handle<v8::DataView> dv) {
2651 CHECK_EQ(0, static_cast<int>(dv->ByteLength()));
2652 CHECK_EQ(0, static_cast<int>(dv->ByteOffset()));
2656 static void CheckIsNeutered(v8::Handle<v8::TypedArray> ta) {
2657 CHECK_EQ(0, static_cast<int>(ta->ByteLength()));
2658 CHECK_EQ(0, static_cast<int>(ta->Length()));
2659 CHECK_EQ(0, static_cast<int>(ta->ByteOffset()));
2663 static void CheckIsTypedArrayVarNeutered(const char* name) {
2664 i::ScopedVector<char> source(1024);
2666 "%s.byteLength == 0 && %s.byteOffset == 0 && %s.length == 0",
2668 CHECK(CompileRun(source.start())->IsTrue());
2669 v8::Handle<v8::TypedArray> ta =
2670 v8::Handle<v8::TypedArray>::Cast(CompileRun(name));
2671 CheckIsNeutered(ta);
2675 template <typename TypedArray, int kElementSize>
2676 static Handle<TypedArray> CreateAndCheck(Handle<v8::ArrayBuffer> ab,
2677 int byteOffset, int length) {
2678 v8::Handle<TypedArray> ta = TypedArray::New(ab, byteOffset, length);
2679 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
2680 CHECK_EQ(byteOffset, static_cast<int>(ta->ByteOffset()));
2681 CHECK_EQ(length, static_cast<int>(ta->Length()));
2682 CHECK_EQ(length * kElementSize, static_cast<int>(ta->ByteLength()));
2687 THREADED_TEST(ArrayBuffer_NeuteringApi) {
2689 v8::Isolate* isolate = env->GetIsolate();
2690 v8::HandleScope handle_scope(isolate);
2692 v8::Handle<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New(isolate, 1024);
2694 v8::Handle<v8::Uint8Array> u8a =
2695 CreateAndCheck<v8::Uint8Array, 1>(buffer, 1, 1023);
2696 v8::Handle<v8::Uint8ClampedArray> u8c =
2697 CreateAndCheck<v8::Uint8ClampedArray, 1>(buffer, 1, 1023);
2698 v8::Handle<v8::Int8Array> i8a =
2699 CreateAndCheck<v8::Int8Array, 1>(buffer, 1, 1023);
2701 v8::Handle<v8::Uint16Array> u16a =
2702 CreateAndCheck<v8::Uint16Array, 2>(buffer, 2, 511);
2703 v8::Handle<v8::Int16Array> i16a =
2704 CreateAndCheck<v8::Int16Array, 2>(buffer, 2, 511);
2706 v8::Handle<v8::Uint32Array> u32a =
2707 CreateAndCheck<v8::Uint32Array, 4>(buffer, 4, 255);
2708 v8::Handle<v8::Int32Array> i32a =
2709 CreateAndCheck<v8::Int32Array, 4>(buffer, 4, 255);
2711 v8::Handle<v8::Float32Array> f32a =
2712 CreateAndCheck<v8::Float32Array, 4>(buffer, 4, 255);
2713 v8::Handle<v8::Float64Array> f64a =
2714 CreateAndCheck<v8::Float64Array, 8>(buffer, 8, 127);
2716 v8::Handle<v8::DataView> dv = v8::DataView::New(buffer, 1, 1023);
2717 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
2718 CHECK_EQ(1, static_cast<int>(dv->ByteOffset()));
2719 CHECK_EQ(1023, static_cast<int>(dv->ByteLength()));
2721 ScopedArrayBufferContents contents(buffer->Externalize());
2723 CHECK_EQ(0, static_cast<int>(buffer->ByteLength()));
2724 CheckIsNeutered(u8a);
2725 CheckIsNeutered(u8c);
2726 CheckIsNeutered(i8a);
2727 CheckIsNeutered(u16a);
2728 CheckIsNeutered(i16a);
2729 CheckIsNeutered(u32a);
2730 CheckIsNeutered(i32a);
2731 CheckIsNeutered(f32a);
2732 CheckIsNeutered(f64a);
2733 CheckDataViewIsNeutered(dv);
2737 THREADED_TEST(ArrayBuffer_NeuteringScript) {
2739 v8::Isolate* isolate = env->GetIsolate();
2740 v8::HandleScope handle_scope(isolate);
2743 "var ab = new ArrayBuffer(1024);"
2744 "var u8a = new Uint8Array(ab, 1, 1023);"
2745 "var u8c = new Uint8ClampedArray(ab, 1, 1023);"
2746 "var i8a = new Int8Array(ab, 1, 1023);"
2747 "var u16a = new Uint16Array(ab, 2, 511);"
2748 "var i16a = new Int16Array(ab, 2, 511);"
2749 "var u32a = new Uint32Array(ab, 4, 255);"
2750 "var i32a = new Int32Array(ab, 4, 255);"
2751 "var f32a = new Float32Array(ab, 4, 255);"
2752 "var f64a = new Float64Array(ab, 8, 127);"
2753 "var dv = new DataView(ab, 1, 1023);");
2755 v8::Handle<v8::ArrayBuffer> ab =
2756 Local<v8::ArrayBuffer>::Cast(CompileRun("ab"));
2758 v8::Handle<v8::DataView> dv =
2759 v8::Handle<v8::DataView>::Cast(CompileRun("dv"));
2761 ScopedArrayBufferContents contents(ab->Externalize());
2763 CHECK_EQ(0, static_cast<int>(ab->ByteLength()));
2764 CHECK_EQ(0, CompileRun("ab.byteLength")->Int32Value());
2766 CheckIsTypedArrayVarNeutered("u8a");
2767 CheckIsTypedArrayVarNeutered("u8c");
2768 CheckIsTypedArrayVarNeutered("i8a");
2769 CheckIsTypedArrayVarNeutered("u16a");
2770 CheckIsTypedArrayVarNeutered("i16a");
2771 CheckIsTypedArrayVarNeutered("u32a");
2772 CheckIsTypedArrayVarNeutered("i32a");
2773 CheckIsTypedArrayVarNeutered("f32a");
2774 CheckIsTypedArrayVarNeutered("f64a");
2776 CHECK(CompileRun("dv.byteLength == 0 && dv.byteOffset == 0")->IsTrue());
2777 CheckDataViewIsNeutered(dv);
2781 class ScopedSharedArrayBufferContents {
2783 explicit ScopedSharedArrayBufferContents(
2784 const v8::SharedArrayBuffer::Contents& contents)
2785 : contents_(contents) {}
2786 ~ScopedSharedArrayBufferContents() { free(contents_.Data()); }
2787 void* Data() const { return contents_.Data(); }
2788 size_t ByteLength() const { return contents_.ByteLength(); }
2791 const v8::SharedArrayBuffer::Contents contents_;
2795 THREADED_TEST(SharedArrayBuffer_ApiInternalToExternal) {
2796 i::FLAG_harmony_sharedarraybuffer = true;
2798 v8::Isolate* isolate = env->GetIsolate();
2799 v8::HandleScope handle_scope(isolate);
2801 Local<v8::SharedArrayBuffer> ab = v8::SharedArrayBuffer::New(isolate, 1024);
2802 CheckInternalFieldsAreZero(ab);
2803 CHECK_EQ(1024, static_cast<int>(ab->ByteLength()));
2804 CHECK(!ab->IsExternal());
2805 CcTest::heap()->CollectAllGarbage();
2807 ScopedSharedArrayBufferContents ab_contents(ab->Externalize());
2808 CHECK(ab->IsExternal());
2810 CHECK_EQ(1024, static_cast<int>(ab_contents.ByteLength()));
2811 uint8_t* data = static_cast<uint8_t*>(ab_contents.Data());
2812 DCHECK(data != NULL);
2813 env->Global()->Set(v8_str("ab"), ab);
2815 v8::Handle<v8::Value> result = CompileRun("ab.byteLength");
2816 CHECK_EQ(1024, result->Int32Value());
2818 result = CompileRun(
2819 "var u8 = new Uint8Array(ab);"
2823 CHECK_EQ(1024, result->Int32Value());
2824 CHECK_EQ(0xFF, data[0]);
2825 CHECK_EQ(0xAA, data[1]);
2828 result = CompileRun("u8[0] + u8[1]");
2829 CHECK_EQ(0xDD, result->Int32Value());
2833 THREADED_TEST(SharedArrayBuffer_JSInternalToExternal) {
2834 i::FLAG_harmony_sharedarraybuffer = true;
2836 v8::Isolate* isolate = env->GetIsolate();
2837 v8::HandleScope handle_scope(isolate);
2840 v8::Local<v8::Value> result = CompileRun(
2841 "var ab1 = new SharedArrayBuffer(2);"
2842 "var u8_a = new Uint8Array(ab1);"
2844 "u8_a[1] = 0xFF; u8_a.buffer");
2845 Local<v8::SharedArrayBuffer> ab1 = Local<v8::SharedArrayBuffer>::Cast(result);
2846 CheckInternalFieldsAreZero(ab1);
2847 CHECK_EQ(2, static_cast<int>(ab1->ByteLength()));
2848 CHECK(!ab1->IsExternal());
2849 ScopedSharedArrayBufferContents ab1_contents(ab1->Externalize());
2850 CHECK(ab1->IsExternal());
2852 result = CompileRun("ab1.byteLength");
2853 CHECK_EQ(2, result->Int32Value());
2854 result = CompileRun("u8_a[0]");
2855 CHECK_EQ(0xAA, result->Int32Value());
2856 result = CompileRun("u8_a[1]");
2857 CHECK_EQ(0xFF, result->Int32Value());
2858 result = CompileRun(
2859 "var u8_b = new Uint8Array(ab1);"
2862 CHECK_EQ(0xBB, result->Int32Value());
2863 result = CompileRun("u8_b[1]");
2864 CHECK_EQ(0xFF, result->Int32Value());
2866 CHECK_EQ(2, static_cast<int>(ab1_contents.ByteLength()));
2867 uint8_t* ab1_data = static_cast<uint8_t*>(ab1_contents.Data());
2868 CHECK_EQ(0xBB, ab1_data[0]);
2869 CHECK_EQ(0xFF, ab1_data[1]);
2872 result = CompileRun("u8_a[0] + u8_a[1]");
2873 CHECK_EQ(0xDD, result->Int32Value());
2877 THREADED_TEST(SharedArrayBuffer_External) {
2878 i::FLAG_harmony_sharedarraybuffer = true;
2880 v8::Isolate* isolate = env->GetIsolate();
2881 v8::HandleScope handle_scope(isolate);
2883 i::ScopedVector<uint8_t> my_data(100);
2884 memset(my_data.start(), 0, 100);
2885 Local<v8::SharedArrayBuffer> ab3 =
2886 v8::SharedArrayBuffer::New(isolate, my_data.start(), 100);
2887 CheckInternalFieldsAreZero(ab3);
2888 CHECK_EQ(100, static_cast<int>(ab3->ByteLength()));
2889 CHECK(ab3->IsExternal());
2891 env->Global()->Set(v8_str("ab3"), ab3);
2893 v8::Handle<v8::Value> result = CompileRun("ab3.byteLength");
2894 CHECK_EQ(100, result->Int32Value());
2896 result = CompileRun(
2897 "var u8_b = new Uint8Array(ab3);"
2901 CHECK_EQ(100, result->Int32Value());
2902 CHECK_EQ(0xBB, my_data[0]);
2903 CHECK_EQ(0xCC, my_data[1]);
2906 result = CompileRun("u8_b[0] + u8_b[1]");
2907 CHECK_EQ(0xDD, result->Int32Value());
2911 THREADED_TEST(HiddenProperties) {
2913 v8::Isolate* isolate = env->GetIsolate();
2914 v8::HandleScope scope(isolate);
2916 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2917 v8::Local<v8::String> key = v8_str("api-test::hidden-key");
2918 v8::Local<v8::String> empty = v8_str("");
2919 v8::Local<v8::String> prop_name = v8_str("prop_name");
2921 CcTest::heap()->CollectAllGarbage();
2923 // Make sure delete of a non-existent hidden value works
2924 CHECK(obj->DeleteHiddenValue(key));
2926 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 1503)));
2927 CHECK_EQ(1503, obj->GetHiddenValue(key)->Int32Value());
2928 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2929 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2931 CcTest::heap()->CollectAllGarbage();
2933 // Make sure we do not find the hidden property.
2934 CHECK(!obj->Has(empty));
2935 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2936 CHECK(obj->Get(empty)->IsUndefined());
2937 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2938 CHECK(obj->Set(empty, v8::Integer::New(isolate, 2003)));
2939 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2940 CHECK_EQ(2003, obj->Get(empty)->Int32Value());
2942 CcTest::heap()->CollectAllGarbage();
2944 // Add another property and delete it afterwards to force the object in
2946 CHECK(obj->Set(prop_name, v8::Integer::New(isolate, 2008)));
2947 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2948 CHECK_EQ(2008, obj->Get(prop_name)->Int32Value());
2949 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2950 CHECK(obj->Delete(prop_name));
2951 CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
2953 CcTest::heap()->CollectAllGarbage();
2955 CHECK(obj->SetHiddenValue(key, Handle<Value>()));
2956 CHECK(obj->GetHiddenValue(key).IsEmpty());
2958 CHECK(obj->SetHiddenValue(key, v8::Integer::New(isolate, 2002)));
2959 CHECK(obj->DeleteHiddenValue(key));
2960 CHECK(obj->GetHiddenValue(key).IsEmpty());
2964 THREADED_TEST(Regress97784) {
2965 // Regression test for crbug.com/97784
2966 // Messing with the Object.prototype should not have effect on
2967 // hidden properties.
2969 v8::HandleScope scope(env->GetIsolate());
2971 v8::Local<v8::Object> obj = v8::Object::New(env->GetIsolate());
2972 v8::Local<v8::String> key = v8_str("hidden");
2975 "set_called = false;"
2976 "Object.defineProperty("
2977 " Object.prototype,"
2979 " {get: function() { return 45; },"
2980 " set: function() { set_called = true; }})");
2982 CHECK(obj->GetHiddenValue(key).IsEmpty());
2983 // Make sure that the getter and setter from Object.prototype is not invoked.
2984 // If it did we would have full access to the hidden properties in
2986 CHECK(obj->SetHiddenValue(key, v8::Integer::New(env->GetIsolate(), 42)));
2987 ExpectFalse("set_called");
2988 CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value());
2992 THREADED_TEST(External) {
2993 v8::HandleScope scope(CcTest::isolate());
2995 Local<v8::External> ext = v8::External::New(CcTest::isolate(), &x);
2997 env->Global()->Set(v8_str("ext"), ext);
2998 Local<Value> reext_obj = CompileRun("this.ext");
2999 v8::Handle<v8::External> reext = reext_obj.As<v8::External>();
3000 int* ptr = static_cast<int*>(reext->Value());
3005 // Make sure unaligned pointers are wrapped properly.
3006 char* data = i::StrDup("0123456789");
3007 Local<v8::Value> zero = v8::External::New(CcTest::isolate(), &data[0]);
3008 Local<v8::Value> one = v8::External::New(CcTest::isolate(), &data[1]);
3009 Local<v8::Value> two = v8::External::New(CcTest::isolate(), &data[2]);
3010 Local<v8::Value> three = v8::External::New(CcTest::isolate(), &data[3]);
3012 char* char_ptr = reinterpret_cast<char*>(v8::External::Cast(*zero)->Value());
3013 CHECK_EQ('0', *char_ptr);
3014 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*one)->Value());
3015 CHECK_EQ('1', *char_ptr);
3016 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*two)->Value());
3017 CHECK_EQ('2', *char_ptr);
3018 char_ptr = reinterpret_cast<char*>(v8::External::Cast(*three)->Value());
3019 CHECK_EQ('3', *char_ptr);
3020 i::DeleteArray(data);
3024 THREADED_TEST(GlobalHandle) {
3025 v8::Isolate* isolate = CcTest::isolate();
3026 v8::Persistent<String> global;
3028 v8::HandleScope scope(isolate);
3029 global.Reset(isolate, v8_str("str"));
3032 v8::HandleScope scope(isolate);
3033 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3037 v8::HandleScope scope(isolate);
3038 global.Reset(isolate, v8_str("str"));
3041 v8::HandleScope scope(isolate);
3042 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3048 THREADED_TEST(ResettingGlobalHandle) {
3049 v8::Isolate* isolate = CcTest::isolate();
3050 v8::Persistent<String> global;
3052 v8::HandleScope scope(isolate);
3053 global.Reset(isolate, v8_str("str"));
3055 v8::internal::GlobalHandles* global_handles =
3056 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3057 int initial_handle_count = global_handles->global_handles_count();
3059 v8::HandleScope scope(isolate);
3060 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3063 v8::HandleScope scope(isolate);
3064 global.Reset(isolate, v8_str("longer"));
3066 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count);
3068 v8::HandleScope scope(isolate);
3069 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 6);
3072 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3076 THREADED_TEST(ResettingGlobalHandleToEmpty) {
3077 v8::Isolate* isolate = CcTest::isolate();
3078 v8::Persistent<String> global;
3080 v8::HandleScope scope(isolate);
3081 global.Reset(isolate, v8_str("str"));
3083 v8::internal::GlobalHandles* global_handles =
3084 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3085 int initial_handle_count = global_handles->global_handles_count();
3087 v8::HandleScope scope(isolate);
3088 CHECK_EQ(v8::Local<String>::New(isolate, global)->Length(), 3);
3091 v8::HandleScope scope(isolate);
3092 Local<String> empty;
3093 global.Reset(isolate, empty);
3095 CHECK(global.IsEmpty());
3096 CHECK_EQ(global_handles->global_handles_count(), initial_handle_count - 1);
3101 static v8::Global<T> PassUnique(v8::Global<T> unique) {
3102 return unique.Pass();
3107 static v8::Global<T> ReturnUnique(v8::Isolate* isolate,
3108 const v8::Persistent<T>& global) {
3109 v8::Global<String> unique(isolate, global);
3110 return unique.Pass();
3114 THREADED_TEST(Global) {
3115 v8::Isolate* isolate = CcTest::isolate();
3116 v8::Persistent<String> global;
3118 v8::HandleScope scope(isolate);
3119 global.Reset(isolate, v8_str("str"));
3121 v8::internal::GlobalHandles* global_handles =
3122 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3123 int initial_handle_count = global_handles->global_handles_count();
3125 v8::Global<String> unique(isolate, global);
3126 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3127 // Test assignment via Pass
3129 v8::Global<String> copy = unique.Pass();
3130 CHECK(unique.IsEmpty());
3131 CHECK(copy == global);
3132 CHECK_EQ(initial_handle_count + 1,
3133 global_handles->global_handles_count());
3134 unique = copy.Pass();
3136 // Test ctor via Pass
3138 v8::Global<String> copy(unique.Pass());
3139 CHECK(unique.IsEmpty());
3140 CHECK(copy == global);
3141 CHECK_EQ(initial_handle_count + 1,
3142 global_handles->global_handles_count());
3143 unique = copy.Pass();
3145 // Test pass through function call
3147 v8::Global<String> copy = PassUnique(unique.Pass());
3148 CHECK(unique.IsEmpty());
3149 CHECK(copy == global);
3150 CHECK_EQ(initial_handle_count + 1,
3151 global_handles->global_handles_count());
3152 unique = copy.Pass();
3154 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3156 // Test pass from function call
3158 v8::Global<String> unique = ReturnUnique(isolate, global);
3159 CHECK(unique == global);
3160 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3162 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3169 class TwoPassCallbackData;
3170 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3171 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data);
3174 class TwoPassCallbackData {
3176 TwoPassCallbackData(v8::Isolate* isolate, int* instance_counter)
3177 : first_pass_called_(false),
3178 second_pass_called_(false),
3180 instance_counter_(instance_counter) {
3181 HandleScope scope(isolate);
3182 i::ScopedVector<char> buffer(40);
3183 i::SNPrintF(buffer, "%p", static_cast<void*>(this));
3185 v8::String::NewFromUtf8(isolate, buffer.start(),
3186 v8::NewStringType::kNormal).ToLocalChecked();
3187 cell_.Reset(isolate, string);
3188 (*instance_counter_)++;
3191 ~TwoPassCallbackData() {
3192 CHECK(first_pass_called_);
3193 CHECK(second_pass_called_);
3194 CHECK(cell_.IsEmpty());
3195 (*instance_counter_)--;
3199 CHECK(!first_pass_called_);
3200 CHECK(!second_pass_called_);
3201 CHECK(!cell_.IsEmpty());
3203 first_pass_called_ = true;
3207 CHECK(first_pass_called_);
3208 CHECK(!second_pass_called_);
3209 CHECK(cell_.IsEmpty());
3210 second_pass_called_ = true;
3215 cell_.SetWeak(this, FirstPassCallback, v8::WeakCallbackType::kParameter);
3218 void MarkTriggerGc() { trigger_gc_ = true; }
3219 bool trigger_gc() { return trigger_gc_; }
3221 int* instance_counter() { return instance_counter_; }
3224 bool first_pass_called_;
3225 bool second_pass_called_;
3227 v8::Global<v8::String> cell_;
3228 int* instance_counter_;
3232 void SecondPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3233 ApiTestFuzzer::Fuzz();
3234 bool trigger_gc = data.GetParameter()->trigger_gc();
3235 int* instance_counter = data.GetParameter()->instance_counter();
3236 data.GetParameter()->SecondPass();
3237 if (!trigger_gc) return;
3238 auto data_2 = new TwoPassCallbackData(data.GetIsolate(), instance_counter);
3240 CcTest::heap()->CollectAllGarbage();
3244 void FirstPassCallback(const v8::WeakCallbackInfo<TwoPassCallbackData>& data) {
3245 data.GetParameter()->FirstPass();
3246 data.SetSecondPassCallback(SecondPassCallback);
3252 TEST(TwoPassPhantomCallbacks) {
3253 auto isolate = CcTest::isolate();
3254 const size_t kLength = 20;
3255 int instance_counter = 0;
3256 for (size_t i = 0; i < kLength; ++i) {
3257 auto data = new TwoPassCallbackData(isolate, &instance_counter);
3260 CHECK_EQ(static_cast<int>(kLength), instance_counter);
3261 CcTest::heap()->CollectAllGarbage();
3262 EmptyMessageQueues(isolate);
3263 CHECK_EQ(0, instance_counter);
3267 TEST(TwoPassPhantomCallbacksNestedGc) {
3268 auto isolate = CcTest::isolate();
3269 const size_t kLength = 20;
3270 TwoPassCallbackData* array[kLength];
3271 int instance_counter = 0;
3272 for (size_t i = 0; i < kLength; ++i) {
3273 array[i] = new TwoPassCallbackData(isolate, &instance_counter);
3274 array[i]->SetWeak();
3276 array[5]->MarkTriggerGc();
3277 array[10]->MarkTriggerGc();
3278 array[15]->MarkTriggerGc();
3279 CHECK_EQ(static_cast<int>(kLength), instance_counter);
3280 CcTest::heap()->CollectAllGarbage();
3281 EmptyMessageQueues(isolate);
3282 CHECK_EQ(0, instance_counter);
3288 void* IntKeyToVoidPointer(int key) { return reinterpret_cast<void*>(key << 1); }
3291 Local<v8::Object> NewObjectForIntKey(
3292 v8::Isolate* isolate, const v8::Global<v8::ObjectTemplate>& templ,
3294 auto local = Local<v8::ObjectTemplate>::New(isolate, templ);
3295 auto obj = local->NewInstance();
3296 obj->SetAlignedPointerInInternalField(0, IntKeyToVoidPointer(key));
3301 template <typename K, typename V>
3302 class PhantomStdMapTraits : public v8::StdMapTraits<K, V> {
3304 typedef typename v8::GlobalValueMap<K, V, PhantomStdMapTraits<K, V>> MapType;
3305 static const v8::PersistentContainerCallbackType kCallbackType =
3306 v8::kWeakWithInternalFields;
3307 struct WeakCallbackDataType {
3311 static WeakCallbackDataType* WeakCallbackParameter(MapType* map, const K& key,
3313 WeakCallbackDataType* data = new WeakCallbackDataType;
3318 static MapType* MapFromWeakCallbackInfo(
3319 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
3320 return data.GetParameter()->map;
3322 static K KeyFromWeakCallbackInfo(
3323 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
3324 return data.GetParameter()->key;
3326 static void DisposeCallbackData(WeakCallbackDataType* data) { delete data; }
3327 static void Dispose(v8::Isolate* isolate, v8::Global<V> value, K key) {
3328 CHECK_EQ(IntKeyToVoidPointer(key),
3329 v8::Object::GetAlignedPointerFromInternalField(value, 0));
3331 static void OnWeakCallback(
3332 const v8::WeakCallbackInfo<WeakCallbackDataType>&) {}
3333 static void DisposeWeak(
3334 const v8::WeakCallbackInfo<WeakCallbackDataType>& info) {
3335 K key = KeyFromWeakCallbackInfo(info);
3336 CHECK_EQ(IntKeyToVoidPointer(key), info.GetInternalField(0));
3337 DisposeCallbackData(info.GetParameter());
3342 template <typename Map>
3343 void TestGlobalValueMap() {
3345 v8::Isolate* isolate = env->GetIsolate();
3346 v8::Global<ObjectTemplate> templ;
3348 HandleScope scope(isolate);
3349 auto t = ObjectTemplate::New(isolate);
3350 t->SetInternalFieldCount(1);
3351 templ.Reset(isolate, t);
3354 v8::internal::GlobalHandles* global_handles =
3355 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3356 int initial_handle_count = global_handles->global_handles_count();
3357 CHECK_EQ(0, static_cast<int>(map.Size()));
3359 HandleScope scope(isolate);
3360 Local<v8::Object> obj = map.Get(7);
3361 CHECK(obj.IsEmpty());
3362 Local<v8::Object> expected = v8::Object::New(isolate);
3363 map.Set(7, expected);
3364 CHECK_EQ(1, static_cast<int>(map.Size()));
3366 CHECK(expected->Equals(obj));
3368 typename Map::PersistentValueReference ref = map.GetReference(7);
3369 CHECK(expected->Equals(ref.NewLocal(isolate)));
3371 v8::Global<v8::Object> removed = map.Remove(7);
3372 CHECK_EQ(0, static_cast<int>(map.Size()));
3373 CHECK(expected == removed);
3374 removed = map.Remove(7);
3375 CHECK(removed.IsEmpty());
3376 map.Set(8, expected);
3377 CHECK_EQ(1, static_cast<int>(map.Size()));
3378 map.Set(8, expected);
3379 CHECK_EQ(1, static_cast<int>(map.Size()));
3381 typename Map::PersistentValueReference ref;
3382 Local<v8::Object> expected2 = NewObjectForIntKey(isolate, templ, 8);
3383 removed = map.Set(8, v8::Global<v8::Object>(isolate, expected2), &ref);
3384 CHECK_EQ(1, static_cast<int>(map.Size()));
3385 CHECK(expected == removed);
3386 CHECK(expected2->Equals(ref.NewLocal(isolate)));
3389 CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
3391 CcTest::i_isolate()->heap()->CollectAllGarbage(
3392 i::Heap::kAbortIncrementalMarkingMask);
3396 CHECK_EQ(0, static_cast<int>(map.Size()));
3397 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3399 HandleScope scope(isolate);
3400 Local<v8::Object> value = NewObjectForIntKey(isolate, templ, 9);
3404 CHECK_EQ(0, static_cast<int>(map.Size()));
3405 CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
3411 TEST(GlobalValueMap) {
3412 // Default case, w/o weak callbacks:
3413 TestGlobalValueMap<v8::StdGlobalValueMap<int, v8::Object>>();
3415 // Custom traits with weak callbacks:
3416 typedef v8::GlobalValueMap<int, v8::Object,
3417 PhantomStdMapTraits<int, v8::Object>> WeakMap;
3418 TestGlobalValueMap<WeakMap>();
3422 TEST(PersistentValueVector) {
3424 v8::Isolate* isolate = env->GetIsolate();
3425 v8::internal::GlobalHandles* global_handles =
3426 reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
3427 int handle_count = global_handles->global_handles_count();
3428 HandleScope scope(isolate);
3430 v8::PersistentValueVector<v8::Object> vector(isolate);
3432 Local<v8::Object> obj1 = v8::Object::New(isolate);
3433 Local<v8::Object> obj2 = v8::Object::New(isolate);
3434 v8::Global<v8::Object> obj3(isolate, v8::Object::New(isolate));
3436 CHECK(vector.IsEmpty());
3437 CHECK_EQ(0, static_cast<int>(vector.Size()));
3439 vector.ReserveCapacity(3);
3440 CHECK(vector.IsEmpty());
3442 vector.Append(obj1);
3443 vector.Append(obj2);
3444 vector.Append(obj1);
3445 vector.Append(obj3.Pass());
3446 vector.Append(obj1);
3448 CHECK(!vector.IsEmpty());
3449 CHECK_EQ(5, static_cast<int>(vector.Size()));
3450 CHECK(obj3.IsEmpty());
3451 CHECK(obj1->Equals(vector.Get(0)));
3452 CHECK(obj1->Equals(vector.Get(2)));
3453 CHECK(obj1->Equals(vector.Get(4)));
3454 CHECK(obj2->Equals(vector.Get(1)));
3456 CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
3459 CHECK(vector.IsEmpty());
3460 CHECK_EQ(0, static_cast<int>(vector.Size()));
3461 CHECK_EQ(handle_count, global_handles->global_handles_count());
3465 THREADED_TEST(GlobalHandleUpcast) {
3466 v8::Isolate* isolate = CcTest::isolate();
3467 v8::HandleScope scope(isolate);
3468 v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
3469 v8::Persistent<String> global_string(isolate, local);
3470 v8::Persistent<Value>& global_value =
3471 v8::Persistent<Value>::Cast(global_string);
3472 CHECK(v8::Local<v8::Value>::New(isolate, global_value)->IsString());
3473 CHECK(global_string == v8::Persistent<String>::Cast(global_value));
3474 global_string.Reset();
3478 THREADED_TEST(HandleEquality) {
3479 v8::Isolate* isolate = CcTest::isolate();
3480 v8::Persistent<String> global1;
3481 v8::Persistent<String> global2;
3483 v8::HandleScope scope(isolate);
3484 global1.Reset(isolate, v8_str("str"));
3485 global2.Reset(isolate, v8_str("str2"));
3487 CHECK_EQ(global1 == global1, true);
3488 CHECK_EQ(global1 != global1, false);
3490 v8::HandleScope scope(isolate);
3491 Local<String> local1 = Local<String>::New(isolate, global1);
3492 Local<String> local2 = Local<String>::New(isolate, global2);
3494 CHECK_EQ(global1 == local1, true);
3495 CHECK_EQ(global1 != local1, false);
3496 CHECK_EQ(local1 == global1, true);
3497 CHECK_EQ(local1 != global1, false);
3499 CHECK_EQ(global1 == local2, false);
3500 CHECK_EQ(global1 != local2, true);
3501 CHECK_EQ(local2 == global1, false);
3502 CHECK_EQ(local2 != global1, true);
3504 CHECK_EQ(local1 == local2, false);
3505 CHECK_EQ(local1 != local2, true);
3507 Local<String> anotherLocal1 = Local<String>::New(isolate, global1);
3508 CHECK_EQ(local1 == anotherLocal1, true);
3509 CHECK_EQ(local1 != anotherLocal1, false);
3516 THREADED_TEST(LocalHandle) {
3517 v8::HandleScope scope(CcTest::isolate());
3518 v8::Local<String> local =
3519 v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
3520 CHECK_EQ(local->Length(), 3);
3524 class WeakCallCounter {
3526 explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) {}
3527 int id() { return id_; }
3528 void increment() { number_of_weak_calls_++; }
3529 int NumberOfWeakCalls() { return number_of_weak_calls_; }
3533 int number_of_weak_calls_;
3537 template <typename T>
3538 struct WeakCallCounterAndPersistent {
3539 explicit WeakCallCounterAndPersistent(WeakCallCounter* counter)
3540 : counter(counter) {}
3541 WeakCallCounter* counter;
3542 v8::Persistent<T> handle;
3546 template <typename T>
3547 static void WeakPointerCallback(
3548 const v8::WeakCallbackInfo<WeakCallCounterAndPersistent<T>>& data) {
3549 CHECK_EQ(1234, data.GetParameter()->counter->id());
3550 data.GetParameter()->counter->increment();
3551 data.GetParameter()->handle.Reset();
3555 template <typename T>
3556 static UniqueId MakeUniqueId(const Persistent<T>& p) {
3557 return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
3561 THREADED_TEST(ApiObjectGroups) {
3563 v8::Isolate* iso = env->GetIsolate();
3564 HandleScope scope(iso);
3566 WeakCallCounter counter(1234);
3568 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3569 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3570 WeakCallCounterAndPersistent<Value> g1c1(&counter);
3571 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3572 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3573 WeakCallCounterAndPersistent<Value> g2c1(&counter);
3576 HandleScope scope(iso);
3577 g1s1.handle.Reset(iso, Object::New(iso));
3578 g1s2.handle.Reset(iso, Object::New(iso));
3579 g1c1.handle.Reset(iso, Object::New(iso));
3580 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3581 v8::WeakCallbackType::kParameter);
3582 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3583 v8::WeakCallbackType::kParameter);
3584 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3585 v8::WeakCallbackType::kParameter);
3587 g2s1.handle.Reset(iso, Object::New(iso));
3588 g2s2.handle.Reset(iso, Object::New(iso));
3589 g2c1.handle.Reset(iso, Object::New(iso));
3590 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3591 v8::WeakCallbackType::kParameter);
3592 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3593 v8::WeakCallbackType::kParameter);
3594 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3595 v8::WeakCallbackType::kParameter);
3598 WeakCallCounterAndPersistent<Value> root(&counter);
3599 root.handle.Reset(iso, g1s1.handle); // make a root.
3601 // Connect group 1 and 2, make a cycle.
3603 HandleScope scope(iso);
3604 CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>())
3605 ->Set(0, Local<Value>::New(iso, g2s2.handle)));
3606 CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>())
3607 ->Set(0, Local<Value>::New(iso, g1s1.handle)));
3611 UniqueId id1 = MakeUniqueId(g1s1.handle);
3612 UniqueId id2 = MakeUniqueId(g2s2.handle);
3613 iso->SetObjectGroupId(g1s1.handle, id1);
3614 iso->SetObjectGroupId(g1s2.handle, id1);
3615 iso->SetReferenceFromGroup(id1, g1c1.handle);
3616 iso->SetObjectGroupId(g2s1.handle, id2);
3617 iso->SetObjectGroupId(g2s2.handle, id2);
3618 iso->SetReferenceFromGroup(id2, g2c1.handle);
3620 // Do a single full GC, ensure incremental marking is stopped.
3621 v8::internal::Heap* heap =
3622 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3623 heap->CollectAllGarbage();
3625 // All object should be alive.
3626 CHECK_EQ(0, counter.NumberOfWeakCalls());
3629 root.handle.SetWeak(&root, &WeakPointerCallback,
3630 v8::WeakCallbackType::kParameter);
3631 // But make children strong roots---all the objects (except for children)
3632 // should be collectable now.
3633 g1c1.handle.ClearWeak();
3634 g2c1.handle.ClearWeak();
3636 // Groups are deleted, rebuild groups.
3638 UniqueId id1 = MakeUniqueId(g1s1.handle);
3639 UniqueId id2 = MakeUniqueId(g2s2.handle);
3640 iso->SetObjectGroupId(g1s1.handle, id1);
3641 iso->SetObjectGroupId(g1s2.handle, id1);
3642 iso->SetReferenceFromGroup(id1, g1c1.handle);
3643 iso->SetObjectGroupId(g2s1.handle, id2);
3644 iso->SetObjectGroupId(g2s2.handle, id2);
3645 iso->SetReferenceFromGroup(id2, g2c1.handle);
3648 heap->CollectAllGarbage();
3650 // All objects should be gone. 5 global handles in total.
3651 CHECK_EQ(5, counter.NumberOfWeakCalls());
3653 // And now make children weak again and collect them.
3654 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3655 v8::WeakCallbackType::kParameter);
3656 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3657 v8::WeakCallbackType::kParameter);
3659 heap->CollectAllGarbage();
3660 CHECK_EQ(7, counter.NumberOfWeakCalls());
3664 THREADED_TEST(ApiObjectGroupsForSubtypes) {
3666 v8::Isolate* iso = env->GetIsolate();
3667 HandleScope scope(iso);
3669 WeakCallCounter counter(1234);
3671 WeakCallCounterAndPersistent<Object> g1s1(&counter);
3672 WeakCallCounterAndPersistent<String> g1s2(&counter);
3673 WeakCallCounterAndPersistent<String> g1c1(&counter);
3674 WeakCallCounterAndPersistent<Object> g2s1(&counter);
3675 WeakCallCounterAndPersistent<String> g2s2(&counter);
3676 WeakCallCounterAndPersistent<String> g2c1(&counter);
3679 HandleScope scope(iso);
3680 g1s1.handle.Reset(iso, Object::New(iso));
3681 g1s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo1"));
3682 g1c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo2"));
3683 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3684 v8::WeakCallbackType::kParameter);
3685 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3686 v8::WeakCallbackType::kParameter);
3687 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3688 v8::WeakCallbackType::kParameter);
3690 g2s1.handle.Reset(iso, Object::New(iso));
3691 g2s2.handle.Reset(iso, String::NewFromUtf8(iso, "foo3"));
3692 g2c1.handle.Reset(iso, String::NewFromUtf8(iso, "foo4"));
3693 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3694 v8::WeakCallbackType::kParameter);
3695 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3696 v8::WeakCallbackType::kParameter);
3697 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3698 v8::WeakCallbackType::kParameter);
3701 WeakCallCounterAndPersistent<Value> root(&counter);
3702 root.handle.Reset(iso, g1s1.handle); // make a root.
3704 // Connect group 1 and 2, make a cycle.
3706 HandleScope scope(iso);
3707 CHECK(Local<Object>::New(iso, g1s1.handle)
3708 ->Set(0, Local<Object>::New(iso, g2s1.handle)));
3709 CHECK(Local<Object>::New(iso, g2s1.handle)
3710 ->Set(0, Local<Object>::New(iso, g1s1.handle)));
3714 UniqueId id1 = MakeUniqueId(g1s1.handle);
3715 UniqueId id2 = MakeUniqueId(g2s2.handle);
3716 iso->SetObjectGroupId(g1s1.handle, id1);
3717 iso->SetObjectGroupId(g1s2.handle, id1);
3718 iso->SetReference(g1s1.handle, g1c1.handle);
3719 iso->SetObjectGroupId(g2s1.handle, id2);
3720 iso->SetObjectGroupId(g2s2.handle, id2);
3721 iso->SetReferenceFromGroup(id2, g2c1.handle);
3723 // Do a single full GC, ensure incremental marking is stopped.
3724 v8::internal::Heap* heap =
3725 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3726 heap->CollectAllGarbage();
3728 // All object should be alive.
3729 CHECK_EQ(0, counter.NumberOfWeakCalls());
3732 root.handle.SetWeak(&root, &WeakPointerCallback,
3733 v8::WeakCallbackType::kParameter);
3734 // But make children strong roots---all the objects (except for children)
3735 // should be collectable now.
3736 g1c1.handle.ClearWeak();
3737 g2c1.handle.ClearWeak();
3739 // Groups are deleted, rebuild groups.
3741 UniqueId id1 = MakeUniqueId(g1s1.handle);
3742 UniqueId id2 = MakeUniqueId(g2s2.handle);
3743 iso->SetObjectGroupId(g1s1.handle, id1);
3744 iso->SetObjectGroupId(g1s2.handle, id1);
3745 iso->SetReference(g1s1.handle, g1c1.handle);
3746 iso->SetObjectGroupId(g2s1.handle, id2);
3747 iso->SetObjectGroupId(g2s2.handle, id2);
3748 iso->SetReferenceFromGroup(id2, g2c1.handle);
3751 heap->CollectAllGarbage();
3753 // All objects should be gone. 5 global handles in total.
3754 CHECK_EQ(5, counter.NumberOfWeakCalls());
3756 // And now make children weak again and collect them.
3757 g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback,
3758 v8::WeakCallbackType::kParameter);
3759 g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback,
3760 v8::WeakCallbackType::kParameter);
3762 heap->CollectAllGarbage();
3763 CHECK_EQ(7, counter.NumberOfWeakCalls());
3767 THREADED_TEST(ApiObjectGroupsCycle) {
3769 v8::Isolate* iso = env->GetIsolate();
3770 HandleScope scope(iso);
3772 WeakCallCounter counter(1234);
3774 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3775 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3776 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3777 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3778 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3779 WeakCallCounterAndPersistent<Value> g3s2(&counter);
3780 WeakCallCounterAndPersistent<Value> g4s1(&counter);
3781 WeakCallCounterAndPersistent<Value> g4s2(&counter);
3784 HandleScope scope(iso);
3785 g1s1.handle.Reset(iso, Object::New(iso));
3786 g1s2.handle.Reset(iso, Object::New(iso));
3787 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3788 v8::WeakCallbackType::kParameter);
3789 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3790 v8::WeakCallbackType::kParameter);
3791 CHECK(g1s1.handle.IsWeak());
3792 CHECK(g1s2.handle.IsWeak());
3794 g2s1.handle.Reset(iso, Object::New(iso));
3795 g2s2.handle.Reset(iso, Object::New(iso));
3796 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3797 v8::WeakCallbackType::kParameter);
3798 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3799 v8::WeakCallbackType::kParameter);
3800 CHECK(g2s1.handle.IsWeak());
3801 CHECK(g2s2.handle.IsWeak());
3803 g3s1.handle.Reset(iso, Object::New(iso));
3804 g3s2.handle.Reset(iso, Object::New(iso));
3805 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
3806 v8::WeakCallbackType::kParameter);
3807 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
3808 v8::WeakCallbackType::kParameter);
3809 CHECK(g3s1.handle.IsWeak());
3810 CHECK(g3s2.handle.IsWeak());
3812 g4s1.handle.Reset(iso, Object::New(iso));
3813 g4s2.handle.Reset(iso, Object::New(iso));
3814 g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback,
3815 v8::WeakCallbackType::kParameter);
3816 g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback,
3817 v8::WeakCallbackType::kParameter);
3818 CHECK(g4s1.handle.IsWeak());
3819 CHECK(g4s2.handle.IsWeak());
3822 WeakCallCounterAndPersistent<Value> root(&counter);
3823 root.handle.Reset(iso, g1s1.handle); // make a root.
3825 // Connect groups. We're building the following cycle:
3826 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3829 UniqueId id1 = MakeUniqueId(g1s1.handle);
3830 UniqueId id2 = MakeUniqueId(g2s1.handle);
3831 UniqueId id3 = MakeUniqueId(g3s1.handle);
3832 UniqueId id4 = MakeUniqueId(g4s1.handle);
3833 iso->SetObjectGroupId(g1s1.handle, id1);
3834 iso->SetObjectGroupId(g1s2.handle, id1);
3835 iso->SetReferenceFromGroup(id1, g2s1.handle);
3836 iso->SetObjectGroupId(g2s1.handle, id2);
3837 iso->SetObjectGroupId(g2s2.handle, id2);
3838 iso->SetReferenceFromGroup(id2, g3s1.handle);
3839 iso->SetObjectGroupId(g3s1.handle, id3);
3840 iso->SetObjectGroupId(g3s2.handle, id3);
3841 iso->SetReferenceFromGroup(id3, g4s1.handle);
3842 iso->SetObjectGroupId(g4s1.handle, id4);
3843 iso->SetObjectGroupId(g4s2.handle, id4);
3844 iso->SetReferenceFromGroup(id4, g1s1.handle);
3846 // Do a single full GC
3847 v8::internal::Heap* heap =
3848 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3849 heap->CollectAllGarbage();
3851 // All object should be alive.
3852 CHECK_EQ(0, counter.NumberOfWeakCalls());
3855 root.handle.SetWeak(&root, &WeakPointerCallback,
3856 v8::WeakCallbackType::kParameter);
3858 // Groups are deleted, rebuild groups.
3860 UniqueId id1 = MakeUniqueId(g1s1.handle);
3861 UniqueId id2 = MakeUniqueId(g2s1.handle);
3862 UniqueId id3 = MakeUniqueId(g3s1.handle);
3863 UniqueId id4 = MakeUniqueId(g4s1.handle);
3864 iso->SetObjectGroupId(g1s1.handle, id1);
3865 iso->SetObjectGroupId(g1s2.handle, id1);
3866 iso->SetReferenceFromGroup(id1, g2s1.handle);
3867 iso->SetObjectGroupId(g2s1.handle, id2);
3868 iso->SetObjectGroupId(g2s2.handle, id2);
3869 iso->SetReferenceFromGroup(id2, g3s1.handle);
3870 iso->SetObjectGroupId(g3s1.handle, id3);
3871 iso->SetObjectGroupId(g3s2.handle, id3);
3872 iso->SetReferenceFromGroup(id3, g4s1.handle);
3873 iso->SetObjectGroupId(g4s1.handle, id4);
3874 iso->SetObjectGroupId(g4s2.handle, id4);
3875 iso->SetReferenceFromGroup(id4, g1s1.handle);
3878 heap->CollectAllGarbage();
3880 // All objects should be gone. 9 global handles in total.
3881 CHECK_EQ(9, counter.NumberOfWeakCalls());
3885 // TODO(mstarzinger): This should be a THREADED_TEST but causes failures
3886 // on the buildbots, so was made non-threaded for the time being.
3887 TEST(ApiObjectGroupsCycleForScavenger) {
3888 i::FLAG_stress_compaction = false;
3889 i::FLAG_gc_global = false;
3891 v8::Isolate* iso = env->GetIsolate();
3892 HandleScope scope(iso);
3894 WeakCallCounter counter(1234);
3896 WeakCallCounterAndPersistent<Value> g1s1(&counter);
3897 WeakCallCounterAndPersistent<Value> g1s2(&counter);
3898 WeakCallCounterAndPersistent<Value> g2s1(&counter);
3899 WeakCallCounterAndPersistent<Value> g2s2(&counter);
3900 WeakCallCounterAndPersistent<Value> g3s1(&counter);
3901 WeakCallCounterAndPersistent<Value> g3s2(&counter);
3904 HandleScope scope(iso);
3905 g1s1.handle.Reset(iso, Object::New(iso));
3906 g1s2.handle.Reset(iso, Object::New(iso));
3907 g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback,
3908 v8::WeakCallbackType::kParameter);
3909 g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback,
3910 v8::WeakCallbackType::kParameter);
3912 g2s1.handle.Reset(iso, Object::New(iso));
3913 g2s2.handle.Reset(iso, Object::New(iso));
3914 g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback,
3915 v8::WeakCallbackType::kParameter);
3916 g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback,
3917 v8::WeakCallbackType::kParameter);
3919 g3s1.handle.Reset(iso, Object::New(iso));
3920 g3s2.handle.Reset(iso, Object::New(iso));
3921 g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback,
3922 v8::WeakCallbackType::kParameter);
3923 g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback,
3924 v8::WeakCallbackType::kParameter);
3928 WeakCallCounterAndPersistent<Value> root(&counter);
3929 root.handle.Reset(iso, g1s1.handle);
3930 root.handle.MarkPartiallyDependent();
3932 // Connect groups. We're building the following cycle:
3933 // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other
3936 HandleScope handle_scope(iso);
3937 g1s1.handle.MarkPartiallyDependent();
3938 g1s2.handle.MarkPartiallyDependent();
3939 g2s1.handle.MarkPartiallyDependent();
3940 g2s2.handle.MarkPartiallyDependent();
3941 g3s1.handle.MarkPartiallyDependent();
3942 g3s2.handle.MarkPartiallyDependent();
3943 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3944 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3945 Local<Object>::New(iso, g1s1.handle.As<Object>())
3946 ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3947 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3948 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3949 Local<Object>::New(iso, g2s1.handle.As<Object>())
3950 ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3951 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3952 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3953 Local<Object>::New(iso, g3s1.handle.As<Object>())
3954 ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
3957 v8::internal::Heap* heap =
3958 reinterpret_cast<v8::internal::Isolate*>(iso)->heap();
3959 heap->CollectAllGarbage();
3961 // All objects should be alive.
3962 CHECK_EQ(0, counter.NumberOfWeakCalls());
3965 root.handle.SetWeak(&root, &WeakPointerCallback,
3966 v8::WeakCallbackType::kParameter);
3967 root.handle.MarkPartiallyDependent();
3969 // Groups are deleted, rebuild groups.
3971 HandleScope handle_scope(iso);
3972 g1s1.handle.MarkPartiallyDependent();
3973 g1s2.handle.MarkPartiallyDependent();
3974 g2s1.handle.MarkPartiallyDependent();
3975 g2s2.handle.MarkPartiallyDependent();
3976 g3s1.handle.MarkPartiallyDependent();
3977 g3s2.handle.MarkPartiallyDependent();
3978 iso->SetObjectGroupId(g1s1.handle, UniqueId(1));
3979 iso->SetObjectGroupId(g1s2.handle, UniqueId(1));
3980 Local<Object>::New(iso, g1s1.handle.As<Object>())
3981 ->Set(v8_str("x"), Local<Value>::New(iso, g2s1.handle));
3982 iso->SetObjectGroupId(g2s1.handle, UniqueId(2));
3983 iso->SetObjectGroupId(g2s2.handle, UniqueId(2));
3984 Local<Object>::New(iso, g2s1.handle.As<Object>())
3985 ->Set(v8_str("x"), Local<Value>::New(iso, g3s1.handle));
3986 iso->SetObjectGroupId(g3s1.handle, UniqueId(3));
3987 iso->SetObjectGroupId(g3s2.handle, UniqueId(3));
3988 Local<Object>::New(iso, g3s1.handle.As<Object>())
3989 ->Set(v8_str("x"), Local<Value>::New(iso, g1s1.handle));
3992 heap->CollectAllGarbage();
3994 // All objects should be gone. 7 global handles in total.
3995 CHECK_EQ(7, counter.NumberOfWeakCalls());
3999 THREADED_TEST(ScriptException) {
4001 v8::HandleScope scope(env->GetIsolate());
4002 Local<Script> script = v8_compile("throw 'panama!';");
4003 v8::TryCatch try_catch(env->GetIsolate());
4004 Local<Value> result = script->Run();
4005 CHECK(result.IsEmpty());
4006 CHECK(try_catch.HasCaught());
4007 String::Utf8Value exception_value(try_catch.Exception());
4008 CHECK_EQ(0, strcmp(*exception_value, "panama!"));
4012 TEST(TryCatchCustomException) {
4014 v8::Isolate* isolate = env->GetIsolate();
4015 v8::HandleScope scope(isolate);
4016 v8::TryCatch try_catch(isolate);
4018 "function CustomError() { this.a = 'b'; }"
4019 "(function f() { throw new CustomError(); })();");
4020 CHECK(try_catch.HasCaught());
4021 CHECK(try_catch.Exception()
4024 ->Equals(v8_str("b")));
4028 bool message_received;
4031 static void check_message_0(v8::Handle<v8::Message> message,
4032 v8::Handle<Value> data) {
4033 CHECK_EQ(5.76, data->NumberValue());
4034 CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4035 CHECK(!message->IsSharedCrossOrigin());
4036 message_received = true;
4040 THREADED_TEST(MessageHandler0) {
4041 message_received = false;
4042 v8::HandleScope scope(CcTest::isolate());
4043 CHECK(!message_received);
4044 LocalContext context;
4045 v8::V8::AddMessageListener(check_message_0, v8_num(5.76));
4046 v8::Handle<v8::Script> script = CompileWithOrigin("throw 'error'", "6.75");
4048 CHECK(message_received);
4049 // clear out the message listener
4050 v8::V8::RemoveMessageListeners(check_message_0);
4054 static void check_message_1(v8::Handle<v8::Message> message,
4055 v8::Handle<Value> data) {
4056 CHECK(data->IsNumber());
4057 CHECK_EQ(1337, data->Int32Value());
4058 CHECK(!message->IsSharedCrossOrigin());
4059 message_received = true;
4063 TEST(MessageHandler1) {
4064 message_received = false;
4065 v8::HandleScope scope(CcTest::isolate());
4066 CHECK(!message_received);
4067 v8::V8::AddMessageListener(check_message_1);
4068 LocalContext context;
4069 CompileRun("throw 1337;");
4070 CHECK(message_received);
4071 // clear out the message listener
4072 v8::V8::RemoveMessageListeners(check_message_1);
4076 static void check_message_2(v8::Handle<v8::Message> message,
4077 v8::Handle<Value> data) {
4078 LocalContext context;
4079 CHECK(data->IsObject());
4080 v8::Local<v8::Value> hidden_property =
4081 v8::Object::Cast(*data)->GetHiddenValue(v8_str("hidden key"));
4082 CHECK(v8_str("hidden value")->Equals(hidden_property));
4083 CHECK(!message->IsSharedCrossOrigin());
4084 message_received = true;
4088 TEST(MessageHandler2) {
4089 message_received = false;
4090 v8::HandleScope scope(CcTest::isolate());
4091 CHECK(!message_received);
4092 v8::V8::AddMessageListener(check_message_2);
4093 LocalContext context;
4094 v8::Local<v8::Value> error = v8::Exception::Error(v8_str("custom error"));
4095 v8::Object::Cast(*error)
4096 ->SetHiddenValue(v8_str("hidden key"), v8_str("hidden value"));
4097 context->Global()->Set(v8_str("error"), error);
4098 CompileRun("throw error;");
4099 CHECK(message_received);
4100 // clear out the message listener
4101 v8::V8::RemoveMessageListeners(check_message_2);
4105 static void check_message_3(v8::Handle<v8::Message> message,
4106 v8::Handle<Value> data) {
4107 CHECK(message->IsSharedCrossOrigin());
4108 CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin());
4109 CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript());
4110 CHECK(message->GetScriptOrigin().Options().IsOpaque());
4111 CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4112 CHECK_EQ(7.40, message->GetScriptOrigin().SourceMapUrl()->NumberValue());
4113 message_received = true;
4117 TEST(MessageHandler3) {
4118 message_received = false;
4119 v8::Isolate* isolate = CcTest::isolate();
4120 v8::HandleScope scope(isolate);
4121 CHECK(!message_received);
4122 v8::V8::AddMessageListener(check_message_3);
4123 LocalContext context;
4124 v8::ScriptOrigin origin = v8::ScriptOrigin(
4125 v8_str("6.75"), v8::Integer::New(isolate, 1),
4126 v8::Integer::New(isolate, 2), v8::True(isolate), Handle<v8::Integer>(),
4127 v8::True(isolate), v8_str("7.40"), v8::True(isolate));
4128 v8::Handle<v8::Script> script =
4129 Script::Compile(v8_str("throw 'error'"), &origin);
4131 CHECK(message_received);
4132 // clear out the message listener
4133 v8::V8::RemoveMessageListeners(check_message_3);
4137 static void check_message_4(v8::Handle<v8::Message> message,
4138 v8::Handle<Value> data) {
4139 CHECK(!message->IsSharedCrossOrigin());
4140 CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4141 message_received = true;
4145 TEST(MessageHandler4) {
4146 message_received = false;
4147 v8::Isolate* isolate = CcTest::isolate();
4148 v8::HandleScope scope(isolate);
4149 CHECK(!message_received);
4150 v8::V8::AddMessageListener(check_message_4);
4151 LocalContext context;
4152 v8::ScriptOrigin origin =
4153 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4154 v8::Integer::New(isolate, 2), v8::False(isolate));
4155 v8::Handle<v8::Script> script =
4156 Script::Compile(v8_str("throw 'error'"), &origin);
4158 CHECK(message_received);
4159 // clear out the message listener
4160 v8::V8::RemoveMessageListeners(check_message_4);
4164 static void check_message_5a(v8::Handle<v8::Message> message,
4165 v8::Handle<Value> data) {
4166 CHECK(message->IsSharedCrossOrigin());
4167 CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4168 message_received = true;
4172 static void check_message_5b(v8::Handle<v8::Message> message,
4173 v8::Handle<Value> data) {
4174 CHECK(!message->IsSharedCrossOrigin());
4175 CHECK_EQ(6.75, message->GetScriptOrigin().ResourceName()->NumberValue());
4176 message_received = true;
4180 TEST(MessageHandler5) {
4181 message_received = false;
4182 v8::Isolate* isolate = CcTest::isolate();
4183 v8::HandleScope scope(isolate);
4184 CHECK(!message_received);
4185 v8::V8::AddMessageListener(check_message_5a);
4186 LocalContext context;
4187 v8::ScriptOrigin origin1 =
4188 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4189 v8::Integer::New(isolate, 2), v8::True(isolate));
4190 v8::Handle<v8::Script> script =
4191 Script::Compile(v8_str("throw 'error'"), &origin1);
4193 CHECK(message_received);
4194 // clear out the message listener
4195 v8::V8::RemoveMessageListeners(check_message_5a);
4197 message_received = false;
4198 v8::V8::AddMessageListener(check_message_5b);
4199 v8::ScriptOrigin origin2 =
4200 v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1),
4201 v8::Integer::New(isolate, 2), v8::False(isolate));
4202 script = Script::Compile(v8_str("throw 'error'"), &origin2);
4204 CHECK(message_received);
4205 // clear out the message listener
4206 v8::V8::RemoveMessageListeners(check_message_5b);
4210 TEST(NativeWeakMap) {
4211 v8::Isolate* isolate = CcTest::isolate();
4212 HandleScope scope(isolate);
4213 Local<v8::NativeWeakMap> weak_map(v8::NativeWeakMap::New(isolate));
4214 CHECK(!weak_map.IsEmpty());
4217 Local<Object> value = v8::Object::New(isolate);
4219 Local<Object> local1 = v8::Object::New(isolate);
4220 CHECK(!weak_map->Has(local1));
4221 CHECK(weak_map->Get(local1)->IsUndefined());
4222 weak_map->Set(local1, value);
4223 CHECK(weak_map->Has(local1));
4224 CHECK(value->Equals(weak_map->Get(local1)));
4226 WeakCallCounter counter(1234);
4227 WeakCallCounterAndPersistent<Value> o1(&counter);
4228 WeakCallCounterAndPersistent<Value> o2(&counter);
4229 WeakCallCounterAndPersistent<Value> s1(&counter);
4231 HandleScope scope(isolate);
4232 Local<v8::Object> obj1 = v8::Object::New(isolate);
4233 Local<v8::Object> obj2 = v8::Object::New(isolate);
4234 Local<v8::Symbol> sym1 = v8::Symbol::New(isolate);
4236 weak_map->Set(obj1, value);
4237 weak_map->Set(obj2, value);
4238 weak_map->Set(sym1, value);
4240 o1.handle.Reset(isolate, obj1);
4241 o2.handle.Reset(isolate, obj2);
4242 s1.handle.Reset(isolate, sym1);
4244 CHECK(weak_map->Has(local1));
4245 CHECK(weak_map->Has(obj1));
4246 CHECK(weak_map->Has(obj2));
4247 CHECK(weak_map->Has(sym1));
4249 CHECK(value->Equals(weak_map->Get(local1)));
4250 CHECK(value->Equals(weak_map->Get(obj1)));
4251 CHECK(value->Equals(weak_map->Get(obj2)));
4252 CHECK(value->Equals(weak_map->Get(sym1)));
4254 CcTest::heap()->CollectAllGarbage();
4256 HandleScope scope(isolate);
4257 CHECK(value->Equals(weak_map->Get(local1)));
4258 CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o1.handle))));
4259 CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, o2.handle))));
4260 CHECK(value->Equals(weak_map->Get(Local<Value>::New(isolate, s1.handle))));
4263 o1.handle.SetWeak(&o1, &WeakPointerCallback,
4264 v8::WeakCallbackType::kParameter);
4265 o2.handle.SetWeak(&o2, &WeakPointerCallback,
4266 v8::WeakCallbackType::kParameter);
4267 s1.handle.SetWeak(&s1, &WeakPointerCallback,
4268 v8::WeakCallbackType::kParameter);
4270 CcTest::heap()->CollectAllGarbage();
4271 CHECK_EQ(3, counter.NumberOfWeakCalls());
4273 CHECK(o1.handle.IsEmpty());
4274 CHECK(o2.handle.IsEmpty());
4275 CHECK(s1.handle.IsEmpty());
4277 CHECK(value->Equals(weak_map->Get(local1)));
4278 CHECK(weak_map->Delete(local1));
4279 CHECK(!weak_map->Has(local1));
4280 CHECK(weak_map->Get(local1)->IsUndefined());
4284 THREADED_TEST(GetSetProperty) {
4285 LocalContext context;
4286 v8::Isolate* isolate = context->GetIsolate();
4287 v8::HandleScope scope(isolate);
4288 context->Global()->Set(v8_str("foo"), v8_num(14));
4289 context->Global()->Set(v8_str("12"), v8_num(92));
4290 context->Global()->Set(v8::Integer::New(isolate, 16), v8_num(32));
4291 context->Global()->Set(v8_num(13), v8_num(56));
4292 Local<Value> foo = CompileRun("this.foo");
4293 CHECK_EQ(14, foo->Int32Value());
4294 Local<Value> twelve = CompileRun("this[12]");
4295 CHECK_EQ(92, twelve->Int32Value());
4296 Local<Value> sixteen = CompileRun("this[16]");
4297 CHECK_EQ(32, sixteen->Int32Value());
4298 Local<Value> thirteen = CompileRun("this[13]");
4299 CHECK_EQ(56, thirteen->Int32Value());
4301 context->Global()->Get(v8::Integer::New(isolate, 12))->Int32Value());
4302 CHECK_EQ(92, context->Global()->Get(v8_str("12"))->Int32Value());
4303 CHECK_EQ(92, context->Global()->Get(v8_num(12))->Int32Value());
4305 context->Global()->Get(v8::Integer::New(isolate, 16))->Int32Value());
4306 CHECK_EQ(32, context->Global()->Get(v8_str("16"))->Int32Value());
4307 CHECK_EQ(32, context->Global()->Get(v8_num(16))->Int32Value());
4309 context->Global()->Get(v8::Integer::New(isolate, 13))->Int32Value());
4310 CHECK_EQ(56, context->Global()->Get(v8_str("13"))->Int32Value());
4311 CHECK_EQ(56, context->Global()->Get(v8_num(13))->Int32Value());
4315 THREADED_TEST(PropertyAttributes) {
4316 LocalContext context;
4317 v8::HandleScope scope(context->GetIsolate());
4319 Local<String> prop = v8_str("none");
4320 context->Global()->Set(prop, v8_num(7));
4321 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4323 prop = v8_str("read_only");
4324 context->Global()->ForceSet(prop, v8_num(7), v8::ReadOnly);
4325 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4326 CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
4327 CompileRun("read_only = 9");
4328 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4329 context->Global()->Set(prop, v8_num(10));
4330 CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
4332 prop = v8_str("dont_delete");
4333 context->Global()->ForceSet(prop, v8_num(13), v8::DontDelete);
4334 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4335 CompileRun("delete dont_delete");
4336 CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
4337 CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
4339 prop = v8_str("dont_enum");
4340 context->Global()->ForceSet(prop, v8_num(28), v8::DontEnum);
4341 CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
4343 prop = v8_str("absent");
4344 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
4345 Local<Value> fake_prop = v8_num(1);
4346 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
4348 TryCatch try_catch(context->GetIsolate());
4349 Local<Value> exception =
4350 CompileRun("({ toString: function() { throw 'exception';} })");
4351 CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
4352 CHECK(try_catch.HasCaught());
4353 String::Utf8Value exception_value(try_catch.Exception());
4354 CHECK_EQ(0, strcmp("exception", *exception_value));
4359 THREADED_TEST(Array) {
4360 LocalContext context;
4361 v8::HandleScope scope(context->GetIsolate());
4362 Local<v8::Array> array = v8::Array::New(context->GetIsolate());
4363 CHECK_EQ(0u, array->Length());
4364 CHECK(array->Get(0)->IsUndefined());
4365 CHECK(!array->Has(0));
4366 CHECK(array->Get(100)->IsUndefined());
4367 CHECK(!array->Has(100));
4368 array->Set(2, v8_num(7));
4369 CHECK_EQ(3u, array->Length());
4370 CHECK(!array->Has(0));
4371 CHECK(!array->Has(1));
4372 CHECK(array->Has(2));
4373 CHECK_EQ(7, array->Get(2)->Int32Value());
4374 Local<Value> obj = CompileRun("[1, 2, 3]");
4375 Local<v8::Array> arr = obj.As<v8::Array>();
4376 CHECK_EQ(3u, arr->Length());
4377 CHECK_EQ(1, arr->Get(0)->Int32Value());
4378 CHECK_EQ(2, arr->Get(1)->Int32Value());
4379 CHECK_EQ(3, arr->Get(2)->Int32Value());
4380 array = v8::Array::New(context->GetIsolate(), 27);
4381 CHECK_EQ(27u, array->Length());
4382 array = v8::Array::New(context->GetIsolate(), -27);
4383 CHECK_EQ(0u, array->Length());
4387 void HandleF(const v8::FunctionCallbackInfo<v8::Value>& args) {
4388 v8::EscapableHandleScope scope(args.GetIsolate());
4389 ApiTestFuzzer::Fuzz();
4390 Local<v8::Array> result = v8::Array::New(args.GetIsolate(), args.Length());
4391 for (int i = 0; i < args.Length(); i++) result->Set(i, args[i]);
4392 args.GetReturnValue().Set(scope.Escape(result));
4396 THREADED_TEST(Vector) {
4397 v8::Isolate* isolate = CcTest::isolate();
4398 v8::HandleScope scope(isolate);
4399 Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
4400 global->Set(v8_str("f"), v8::FunctionTemplate::New(isolate, HandleF));
4401 LocalContext context(0, global);
4403 const char* fun = "f()";
4404 Local<v8::Array> a0 = CompileRun(fun).As<v8::Array>();
4405 CHECK_EQ(0u, a0->Length());
4407 const char* fun2 = "f(11)";
4408 Local<v8::Array> a1 = CompileRun(fun2).As<v8::Array>();
4409 CHECK_EQ(1u, a1->Length());
4410 CHECK_EQ(11, a1->Get(0)->Int32Value());
4412 const char* fun3 = "f(12, 13)";
4413 Local<v8::Array> a2 = CompileRun(fun3).As<v8::Array>();
4414 CHECK_EQ(2u, a2->Length());
4415 CHECK_EQ(12, a2->Get(0)->Int32Value());
4416 CHECK_EQ(13, a2->Get(1)->Int32Value());
4418 const char* fun4 = "f(14, 15, 16)";
4419 Local<v8::Array> a3 = CompileRun(fun4).As<v8::Array>();
4420 CHECK_EQ(3u, a3->Length());
4421 CHECK_EQ(14, a3->Get(0)->Int32Value());
4422 CHECK_EQ(15, a3->Get(1)->Int32Value());
4423 CHECK_EQ(16, a3->Get(2)->Int32Value());
4425 const char* fun5 = "f(17, 18, 19, 20)";
4426 Local<v8::Array> a4 = CompileRun(fun5).As<v8::Array>();
4427 CHECK_EQ(4u, a4->Length());
4428 CHECK_EQ(17, a4->Get(0)->Int32Value());
4429 CHECK_EQ(18, a4->Get(1)->Int32Value());
4430 CHECK_EQ(19, a4->Get(2)->Int32Value());
4431 CHECK_EQ(20, a4->Get(3)->Int32Value());
4435 THREADED_TEST(FunctionCall) {
4436 LocalContext context;
4437 v8::Isolate* isolate = context->GetIsolate();
4438 v8::HandleScope scope(isolate);
4442 " for (var i = 0; i < arguments.length; i++) {"
4443 " result.push(arguments[i]);"
4447 "function ReturnThisSloppy() {"
4450 "function ReturnThisStrict() {"
4454 Local<Function> Foo =
4455 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4456 Local<Function> ReturnThisSloppy =
4457 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisSloppy")));
4458 Local<Function> ReturnThisStrict =
4459 Local<Function>::Cast(context->Global()->Get(v8_str("ReturnThisStrict")));
4461 v8::Handle<Value>* args0 = NULL;
4462 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->Call(Foo, 0, args0));
4463 CHECK_EQ(0u, a0->Length());
4465 v8::Handle<Value> args1[] = {v8_num(1.1)};
4466 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->Call(Foo, 1, args1));
4467 CHECK_EQ(1u, a1->Length());
4468 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4470 v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4471 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->Call(Foo, 2, args2));
4472 CHECK_EQ(2u, a2->Length());
4473 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4474 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4476 v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4477 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->Call(Foo, 3, args3));
4478 CHECK_EQ(3u, a3->Length());
4479 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4480 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4481 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4483 v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4485 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->Call(Foo, 4, args4));
4486 CHECK_EQ(4u, a4->Length());
4487 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4488 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4489 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4490 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4492 Local<v8::Value> r1 = ReturnThisSloppy->Call(v8::Undefined(isolate), 0, NULL);
4493 CHECK(r1->StrictEquals(context->Global()));
4494 Local<v8::Value> r2 = ReturnThisSloppy->Call(v8::Null(isolate), 0, NULL);
4495 CHECK(r2->StrictEquals(context->Global()));
4496 Local<v8::Value> r3 = ReturnThisSloppy->Call(v8_num(42), 0, NULL);
4497 CHECK(r3->IsNumberObject());
4498 CHECK_EQ(42.0, r3.As<v8::NumberObject>()->ValueOf());
4499 Local<v8::Value> r4 = ReturnThisSloppy->Call(v8_str("hello"), 0, NULL);
4500 CHECK(r4->IsStringObject());
4501 CHECK(r4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
4502 Local<v8::Value> r5 = ReturnThisSloppy->Call(v8::True(isolate), 0, NULL);
4503 CHECK(r5->IsBooleanObject());
4504 CHECK(r5.As<v8::BooleanObject>()->ValueOf());
4506 Local<v8::Value> r6 = ReturnThisStrict->Call(v8::Undefined(isolate), 0, NULL);
4507 CHECK(r6->IsUndefined());
4508 Local<v8::Value> r7 = ReturnThisStrict->Call(v8::Null(isolate), 0, NULL);
4509 CHECK(r7->IsNull());
4510 Local<v8::Value> r8 = ReturnThisStrict->Call(v8_num(42), 0, NULL);
4511 CHECK(r8->StrictEquals(v8_num(42)));
4512 Local<v8::Value> r9 = ReturnThisStrict->Call(v8_str("hello"), 0, NULL);
4513 CHECK(r9->StrictEquals(v8_str("hello")));
4514 Local<v8::Value> r10 = ReturnThisStrict->Call(v8::True(isolate), 0, NULL);
4515 CHECK(r10->StrictEquals(v8::True(isolate)));
4519 THREADED_TEST(ConstructCall) {
4520 LocalContext context;
4521 v8::Isolate* isolate = context->GetIsolate();
4522 v8::HandleScope scope(isolate);
4526 " for (var i = 0; i < arguments.length; i++) {"
4527 " result.push(arguments[i]);"
4531 Local<Function> Foo =
4532 Local<Function>::Cast(context->Global()->Get(v8_str("Foo")));
4534 v8::Handle<Value>* args0 = NULL;
4535 Local<v8::Array> a0 = Local<v8::Array>::Cast(Foo->NewInstance(0, args0));
4536 CHECK_EQ(0u, a0->Length());
4538 v8::Handle<Value> args1[] = {v8_num(1.1)};
4539 Local<v8::Array> a1 = Local<v8::Array>::Cast(Foo->NewInstance(1, args1));
4540 CHECK_EQ(1u, a1->Length());
4541 CHECK_EQ(1.1, a1->Get(v8::Integer::New(isolate, 0))->NumberValue());
4543 v8::Handle<Value> args2[] = {v8_num(2.2), v8_num(3.3)};
4544 Local<v8::Array> a2 = Local<v8::Array>::Cast(Foo->NewInstance(2, args2));
4545 CHECK_EQ(2u, a2->Length());
4546 CHECK_EQ(2.2, a2->Get(v8::Integer::New(isolate, 0))->NumberValue());
4547 CHECK_EQ(3.3, a2->Get(v8::Integer::New(isolate, 1))->NumberValue());
4549 v8::Handle<Value> args3[] = {v8_num(4.4), v8_num(5.5), v8_num(6.6)};
4550 Local<v8::Array> a3 = Local<v8::Array>::Cast(Foo->NewInstance(3, args3));
4551 CHECK_EQ(3u, a3->Length());
4552 CHECK_EQ(4.4, a3->Get(v8::Integer::New(isolate, 0))->NumberValue());
4553 CHECK_EQ(5.5, a3->Get(v8::Integer::New(isolate, 1))->NumberValue());
4554 CHECK_EQ(6.6, a3->Get(v8::Integer::New(isolate, 2))->NumberValue());
4556 v8::Handle<Value> args4[] = {v8_num(7.7), v8_num(8.8), v8_num(9.9),
4558 Local<v8::Array> a4 = Local<v8::Array>::Cast(Foo->NewInstance(4, args4));
4559 CHECK_EQ(4u, a4->Length());
4560 CHECK_EQ(7.7, a4->Get(v8::Integer::New(isolate, 0))->NumberValue());
4561 CHECK_EQ(8.8, a4->Get(v8::Integer::New(isolate, 1))->NumberValue());
4562 CHECK_EQ(9.9, a4->Get(v8::Integer::New(isolate, 2))->NumberValue());
4563 CHECK_EQ(10.11, a4->Get(v8::Integer::New(isolate, 3))->NumberValue());
4567 static void CheckUncle(v8::TryCatch* try_catch) {
4568 CHECK(try_catch->HasCaught());
4569 String::Utf8Value str_value(try_catch->Exception());
4570 CHECK_EQ(0, strcmp(*str_value, "uncle?"));
4575 THREADED_TEST(ConversionNumber) {
4577 v8::Isolate* isolate = env->GetIsolate();
4578 v8::HandleScope scope(isolate);
4579 // Very large number.
4580 CompileRun("var obj = Math.pow(2,32) * 1237;");
4581 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4582 CHECK_EQ(5312874545152.0, obj->ToNumber(isolate)->Value());
4583 CHECK_EQ(0, obj->ToInt32(isolate)->Value());
4585 obj->ToUint32(isolate)->Value()); // NOLINT - no CHECK_EQ for unsigned.
4587 CompileRun("var obj = -1234567890123;");
4588 obj = env->Global()->Get(v8_str("obj"));
4589 CHECK_EQ(-1234567890123.0, obj->ToNumber(isolate)->Value());
4590 CHECK_EQ(-1912276171, obj->ToInt32(isolate)->Value());
4591 CHECK(2382691125u == obj->ToUint32(isolate)->Value()); // NOLINT
4592 // Small positive integer.
4593 CompileRun("var obj = 42;");
4594 obj = env->Global()->Get(v8_str("obj"));
4595 CHECK_EQ(42.0, obj->ToNumber(isolate)->Value());
4596 CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4597 CHECK(42u == obj->ToUint32(isolate)->Value()); // NOLINT
4598 // Negative integer.
4599 CompileRun("var obj = -37;");
4600 obj = env->Global()->Get(v8_str("obj"));
4601 CHECK_EQ(-37.0, obj->ToNumber(isolate)->Value());
4602 CHECK_EQ(-37, obj->ToInt32(isolate)->Value());
4603 CHECK(4294967259u == obj->ToUint32(isolate)->Value()); // NOLINT
4604 // Positive non-int32 integer.
4605 CompileRun("var obj = 0x81234567;");
4606 obj = env->Global()->Get(v8_str("obj"));
4607 CHECK_EQ(2166572391.0, obj->ToNumber(isolate)->Value());
4608 CHECK_EQ(-2128394905, obj->ToInt32(isolate)->Value());
4609 CHECK(2166572391u == obj->ToUint32(isolate)->Value()); // NOLINT
4611 CompileRun("var obj = 42.3;");
4612 obj = env->Global()->Get(v8_str("obj"));
4613 CHECK_EQ(42.3, obj->ToNumber(isolate)->Value());
4614 CHECK_EQ(42, obj->ToInt32(isolate)->Value());
4615 CHECK(42u == obj->ToUint32(isolate)->Value()); // NOLINT
4616 // Large negative fraction.
4617 CompileRun("var obj = -5726623061.75;");
4618 obj = env->Global()->Get(v8_str("obj"));
4619 CHECK_EQ(-5726623061.75, obj->ToNumber(isolate)->Value());
4620 CHECK_EQ(-1431655765, obj->ToInt32(isolate)->Value());
4621 CHECK(2863311531u == obj->ToUint32(isolate)->Value()); // NOLINT
4625 THREADED_TEST(isNumberType) {
4627 v8::HandleScope scope(env->GetIsolate());
4628 // Very large number.
4629 CompileRun("var obj = Math.pow(2,32) * 1237;");
4630 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4631 CHECK(!obj->IsInt32());
4632 CHECK(!obj->IsUint32());
4633 // Large negative number.
4634 CompileRun("var obj = -1234567890123;");
4635 obj = env->Global()->Get(v8_str("obj"));
4636 CHECK(!obj->IsInt32());
4637 CHECK(!obj->IsUint32());
4638 // Small positive integer.
4639 CompileRun("var obj = 42;");
4640 obj = env->Global()->Get(v8_str("obj"));
4641 CHECK(obj->IsInt32());
4642 CHECK(obj->IsUint32());
4643 // Negative integer.
4644 CompileRun("var obj = -37;");
4645 obj = env->Global()->Get(v8_str("obj"));
4646 CHECK(obj->IsInt32());
4647 CHECK(!obj->IsUint32());
4648 // Positive non-int32 integer.
4649 CompileRun("var obj = 0x81234567;");
4650 obj = env->Global()->Get(v8_str("obj"));
4651 CHECK(!obj->IsInt32());
4652 CHECK(obj->IsUint32());
4654 CompileRun("var obj = 42.3;");
4655 obj = env->Global()->Get(v8_str("obj"));
4656 CHECK(!obj->IsInt32());
4657 CHECK(!obj->IsUint32());
4658 // Large negative fraction.
4659 CompileRun("var obj = -5726623061.75;");
4660 obj = env->Global()->Get(v8_str("obj"));
4661 CHECK(!obj->IsInt32());
4662 CHECK(!obj->IsUint32());
4664 CompileRun("var obj = 0.0;");
4665 obj = env->Global()->Get(v8_str("obj"));
4666 CHECK(obj->IsInt32());
4667 CHECK(obj->IsUint32());
4669 CompileRun("var obj = -0.0;");
4670 obj = env->Global()->Get(v8_str("obj"));
4671 CHECK(!obj->IsInt32());
4672 CHECK(!obj->IsUint32());
4676 THREADED_TEST(ConversionException) {
4678 v8::Isolate* isolate = env->GetIsolate();
4679 v8::HandleScope scope(isolate);
4681 "function TestClass() { };"
4682 "TestClass.prototype.toString = function () { throw 'uncle?'; };"
4683 "var obj = new TestClass();");
4684 Local<Value> obj = env->Global()->Get(v8_str("obj"));
4686 v8::TryCatch try_catch(isolate);
4688 Local<Value> to_string_result = obj->ToString(isolate);
4689 CHECK(to_string_result.IsEmpty());
4690 CheckUncle(&try_catch);
4692 Local<Value> to_number_result = obj->ToNumber(isolate);
4693 CHECK(to_number_result.IsEmpty());
4694 CheckUncle(&try_catch);
4696 Local<Value> to_integer_result = obj->ToInteger(isolate);
4697 CHECK(to_integer_result.IsEmpty());
4698 CheckUncle(&try_catch);
4700 Local<Value> to_uint32_result = obj->ToUint32(isolate);
4701 CHECK(to_uint32_result.IsEmpty());
4702 CheckUncle(&try_catch);
4704 Local<Value> to_int32_result = obj->ToInt32(isolate);
4705 CHECK(to_int32_result.IsEmpty());
4706 CheckUncle(&try_catch);
4708 Local<Value> to_object_result = v8::Undefined(isolate)->ToObject(isolate);
4709 CHECK(to_object_result.IsEmpty());
4710 CHECK(try_catch.HasCaught());
4713 int32_t int32_value = obj->Int32Value();
4714 CHECK_EQ(0, int32_value);
4715 CheckUncle(&try_catch);
4717 uint32_t uint32_value = obj->Uint32Value();
4718 CHECK_EQ(0u, uint32_value);
4719 CheckUncle(&try_catch);
4721 double number_value = obj->NumberValue();
4722 CHECK(std::isnan(number_value));
4723 CheckUncle(&try_catch);
4725 int64_t integer_value = obj->IntegerValue();
4726 CHECK_EQ(0, integer_value);
4727 CheckUncle(&try_catch);
4731 void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
4732 ApiTestFuzzer::Fuzz();
4733 args.GetIsolate()->ThrowException(v8_str("konto"));
4737 void CCatcher(const v8::FunctionCallbackInfo<v8::Value>& args) {
4738 if (args.Length() < 1) {
4739 args.GetReturnValue().Set(false);
4742 v8::HandleScope scope(args.GetIsolate());
4743 v8::TryCatch try_catch(args.GetIsolate());
4744 Local<Value> result = CompileRun(args[0]->ToString(args.GetIsolate()));
4745 CHECK(!try_catch.HasCaught() || result.IsEmpty());
4746 args.GetReturnValue().Set(try_catch.HasCaught());
4750 THREADED_TEST(APICatch) {
4751 v8::Isolate* isolate = CcTest::isolate();
4752 v8::HandleScope scope(isolate);
4753 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4754 templ->Set(v8_str("ThrowFromC"),
4755 v8::FunctionTemplate::New(isolate, ThrowFromC));
4756 LocalContext context(0, templ);
4758 "var thrown = false;"
4764 Local<Value> thrown = context->Global()->Get(v8_str("thrown"));
4765 CHECK(thrown->BooleanValue());
4769 THREADED_TEST(APIThrowTryCatch) {
4770 v8::Isolate* isolate = CcTest::isolate();
4771 v8::HandleScope scope(isolate);
4772 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4773 templ->Set(v8_str("ThrowFromC"),
4774 v8::FunctionTemplate::New(isolate, ThrowFromC));
4775 LocalContext context(0, templ);
4776 v8::TryCatch try_catch(isolate);
4777 CompileRun("ThrowFromC();");
4778 CHECK(try_catch.HasCaught());
4782 // Test that a try-finally block doesn't shadow a try-catch block
4783 // when setting up an external handler.
4785 // BUG(271): Some of the exception propagation does not work on the
4786 // ARM simulator because the simulator separates the C++ stack and the
4787 // JS stack. This test therefore fails on the simulator. The test is
4788 // not threaded to allow the threading tests to run on the simulator.
4789 TEST(TryCatchInTryFinally) {
4790 v8::Isolate* isolate = CcTest::isolate();
4791 v8::HandleScope scope(isolate);
4792 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4793 templ->Set(v8_str("CCatcher"), v8::FunctionTemplate::New(isolate, CCatcher));
4794 LocalContext context(0, templ);
4795 Local<Value> result = CompileRun(
4798 " CCatcher('throw 7;');"
4803 CHECK(result->IsTrue());
4807 static void check_reference_error_message(v8::Handle<v8::Message> message,
4808 v8::Handle<v8::Value> data) {
4809 const char* reference_error = "Uncaught ReferenceError: asdf is not defined";
4810 CHECK(message->Get()->Equals(v8_str(reference_error)));
4814 static void Fail(const v8::FunctionCallbackInfo<v8::Value>& args) {
4815 ApiTestFuzzer::Fuzz();
4820 // Test that overwritten methods are not invoked on uncaught exception
4821 // formatting. However, they are invoked when performing normal error
4822 // string conversions.
4823 TEST(APIThrowMessageOverwrittenToString) {
4824 v8::Isolate* isolate = CcTest::isolate();
4825 v8::HandleScope scope(isolate);
4826 v8::V8::AddMessageListener(check_reference_error_message);
4827 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4828 templ->Set(v8_str("fail"), v8::FunctionTemplate::New(isolate, Fail));
4829 LocalContext context(NULL, templ);
4830 CompileRun("asdf;");
4833 "limit.valueOf = fail;"
4834 "Error.stackTraceLimit = limit;");
4836 CompileRun("Array.prototype.pop = fail;");
4837 CompileRun("Object.prototype.hasOwnProperty = fail;");
4838 CompileRun("Object.prototype.toString = function f() { return 'Yikes'; }");
4839 CompileRun("Number.prototype.toString = function f() { return 'Yikes'; }");
4840 CompileRun("String.prototype.toString = function f() { return 'Yikes'; }");
4842 "ReferenceError.prototype.toString ="
4843 " function() { return 'Whoops' }");
4844 CompileRun("asdf;");
4845 CompileRun("ReferenceError.prototype.constructor.name = void 0;");
4846 CompileRun("asdf;");
4847 CompileRun("ReferenceError.prototype.constructor = void 0;");
4848 CompileRun("asdf;");
4849 CompileRun("ReferenceError.prototype.__proto__ = new Object();");
4850 CompileRun("asdf;");
4851 CompileRun("ReferenceError.prototype = new Object();");
4852 CompileRun("asdf;");
4853 v8::Handle<Value> string = CompileRun("try { asdf; } catch(e) { e + ''; }");
4854 CHECK(string->Equals(v8_str("Whoops")));
4856 "ReferenceError.prototype.constructor = new Object();"
4857 "ReferenceError.prototype.constructor.name = 1;"
4858 "Number.prototype.toString = function() { return 'Whoops'; };"
4859 "ReferenceError.prototype.toString = Object.prototype.toString;");
4860 CompileRun("asdf;");
4861 v8::V8::RemoveMessageListeners(check_reference_error_message);
4865 static void check_custom_error_tostring(v8::Handle<v8::Message> message,
4866 v8::Handle<v8::Value> data) {
4867 const char* uncaught_error = "Uncaught MyError toString";
4868 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4872 TEST(CustomErrorToString) {
4873 LocalContext context;
4874 v8::HandleScope scope(context->GetIsolate());
4875 v8::V8::AddMessageListener(check_custom_error_tostring);
4877 "function MyError(name, message) { "
4878 " this.name = name; "
4879 " this.message = message; "
4881 "MyError.prototype = Object.create(Error.prototype); "
4882 "MyError.prototype.toString = function() { "
4883 " return 'MyError toString'; "
4885 "throw new MyError('my name', 'my message'); ");
4886 v8::V8::RemoveMessageListeners(check_custom_error_tostring);
4890 static void check_custom_error_message(v8::Handle<v8::Message> message,
4891 v8::Handle<v8::Value> data) {
4892 const char* uncaught_error = "Uncaught MyError: my message";
4893 printf("%s\n", *v8::String::Utf8Value(message->Get()));
4894 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4898 TEST(CustomErrorMessage) {
4899 LocalContext context;
4900 v8::HandleScope scope(context->GetIsolate());
4901 v8::V8::AddMessageListener(check_custom_error_message);
4905 "function MyError(msg) { "
4906 " this.name = 'MyError'; "
4907 " this.message = msg; "
4909 "MyError.prototype = new Error(); "
4910 "throw new MyError('my message'); ");
4914 "function MyError(msg) { "
4915 " this.name = 'MyError'; "
4916 " this.message = msg; "
4918 "inherits = function(childCtor, parentCtor) { "
4919 " function tempCtor() {}; "
4920 " tempCtor.prototype = parentCtor.prototype; "
4921 " childCtor.superClass_ = parentCtor.prototype; "
4922 " childCtor.prototype = new tempCtor(); "
4923 " childCtor.prototype.constructor = childCtor; "
4925 "inherits(MyError, Error); "
4926 "throw new MyError('my message'); ");
4930 "function MyError(msg) { "
4931 " this.name = 'MyError'; "
4932 " this.message = msg; "
4934 "MyError.prototype = Object.create(Error.prototype); "
4935 "throw new MyError('my message'); ");
4937 v8::V8::RemoveMessageListeners(check_custom_error_message);
4941 static void check_custom_rethrowing_message(v8::Handle<v8::Message> message,
4942 v8::Handle<v8::Value> data) {
4943 const char* uncaught_error = "Uncaught exception";
4944 CHECK(message->Get()->Equals(v8_str(uncaught_error)));
4948 TEST(CustomErrorRethrowsOnToString) {
4949 LocalContext context;
4950 v8::HandleScope scope(context->GetIsolate());
4951 v8::V8::AddMessageListener(check_custom_rethrowing_message);
4954 "var e = { toString: function() { throw e; } };"
4955 "try { throw e; } finally {}");
4957 v8::V8::RemoveMessageListeners(check_custom_rethrowing_message);
4961 static void receive_message(v8::Handle<v8::Message> message,
4962 v8::Handle<v8::Value> data) {
4964 message_received = true;
4968 TEST(APIThrowMessage) {
4969 message_received = false;
4970 v8::Isolate* isolate = CcTest::isolate();
4971 v8::HandleScope scope(isolate);
4972 v8::V8::AddMessageListener(receive_message);
4973 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4974 templ->Set(v8_str("ThrowFromC"),
4975 v8::FunctionTemplate::New(isolate, ThrowFromC));
4976 LocalContext context(0, templ);
4977 CompileRun("ThrowFromC();");
4978 CHECK(message_received);
4979 v8::V8::RemoveMessageListeners(receive_message);
4983 TEST(APIThrowMessageAndVerboseTryCatch) {
4984 message_received = false;
4985 v8::Isolate* isolate = CcTest::isolate();
4986 v8::HandleScope scope(isolate);
4987 v8::V8::AddMessageListener(receive_message);
4988 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
4989 templ->Set(v8_str("ThrowFromC"),
4990 v8::FunctionTemplate::New(isolate, ThrowFromC));
4991 LocalContext context(0, templ);
4992 v8::TryCatch try_catch(isolate);
4993 try_catch.SetVerbose(true);
4994 Local<Value> result = CompileRun("ThrowFromC();");
4995 CHECK(try_catch.HasCaught());
4996 CHECK(result.IsEmpty());
4997 CHECK(message_received);
4998 v8::V8::RemoveMessageListeners(receive_message);
5002 TEST(APIStackOverflowAndVerboseTryCatch) {
5003 message_received = false;
5004 LocalContext context;
5005 v8::HandleScope scope(context->GetIsolate());
5006 v8::V8::AddMessageListener(receive_message);
5007 v8::TryCatch try_catch(context->GetIsolate());
5008 try_catch.SetVerbose(true);
5009 Local<Value> result = CompileRun("function foo() { foo(); } foo();");
5010 CHECK(try_catch.HasCaught());
5011 CHECK(result.IsEmpty());
5012 CHECK(message_received);
5013 v8::V8::RemoveMessageListeners(receive_message);
5017 THREADED_TEST(ExternalScriptException) {
5018 v8::Isolate* isolate = CcTest::isolate();
5019 v8::HandleScope scope(isolate);
5020 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5021 templ->Set(v8_str("ThrowFromC"),
5022 v8::FunctionTemplate::New(isolate, ThrowFromC));
5023 LocalContext context(0, templ);
5025 v8::TryCatch try_catch(isolate);
5026 Local<Value> result = CompileRun("ThrowFromC(); throw 'panama';");
5027 CHECK(result.IsEmpty());
5028 CHECK(try_catch.HasCaught());
5029 String::Utf8Value exception_value(try_catch.Exception());
5030 CHECK_EQ(0, strcmp("konto", *exception_value));
5034 void CThrowCountDown(const v8::FunctionCallbackInfo<v8::Value>& args) {
5035 ApiTestFuzzer::Fuzz();
5036 CHECK_EQ(4, args.Length());
5037 int count = args[0]->Int32Value();
5038 int cInterval = args[2]->Int32Value();
5040 args.GetIsolate()->ThrowException(v8_str("FromC"));
5043 Local<v8::Object> global = args.GetIsolate()->GetCurrentContext()->Global();
5044 Local<Value> fun = global->Get(v8_str("JSThrowCountDown"));
5045 v8::Handle<Value> argv[] = {v8_num(count - 1), args[1], args[2], args[3]};
5046 if (count % cInterval == 0) {
5047 v8::TryCatch try_catch(args.GetIsolate());
5048 Local<Value> result = fun.As<Function>()->Call(global, 4, argv);
5049 int expected = args[3]->Int32Value();
5050 if (try_catch.HasCaught()) {
5051 CHECK_EQ(expected, count);
5052 CHECK(result.IsEmpty());
5053 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
5055 CHECK_NE(expected, count);
5057 args.GetReturnValue().Set(result);
5060 args.GetReturnValue().Set(fun.As<Function>()->Call(global, 4, argv));
5067 void JSCheck(const v8::FunctionCallbackInfo<v8::Value>& args) {
5068 ApiTestFuzzer::Fuzz();
5069 CHECK_EQ(3, args.Length());
5070 bool equality = args[0]->BooleanValue();
5071 int count = args[1]->Int32Value();
5072 int expected = args[2]->Int32Value();
5074 CHECK_EQ(count, expected);
5076 CHECK_NE(count, expected);
5081 THREADED_TEST(EvalInTryFinally) {
5082 LocalContext context;
5083 v8::HandleScope scope(context->GetIsolate());
5084 v8::TryCatch try_catch(context->GetIsolate());
5088 " eval('asldkf (*&^&*^');"
5093 CHECK(!try_catch.HasCaught());
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.
5105 // The notation used to describe a test case looks like this:
5107 // *JS[4] *C[3] @JS[2] C[1] JS[0]
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.
5113 // BUG(271): Some of the exception propagation does not work on the
5114 // ARM simulator because the simulator separates the C++ stack and the
5115 // JS stack. This test therefore fails on the simulator. The test is
5116 // not threaded to allow the threading tests to run on the simulator.
5117 TEST(ExceptionOrder) {
5118 v8::Isolate* isolate = CcTest::isolate();
5119 v8::HandleScope scope(isolate);
5120 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5121 templ->Set(v8_str("check"), v8::FunctionTemplate::New(isolate, JSCheck));
5122 templ->Set(v8_str("CThrowCountDown"),
5123 v8::FunctionTemplate::New(isolate, CThrowCountDown));
5124 LocalContext context(0, templ);
5126 "function JSThrowCountDown(count, jsInterval, cInterval, expected) {"
5127 " if (count == 0) throw 'FromJS';"
5128 " if (count % jsInterval == 0) {"
5130 " var value = CThrowCountDown(count - 1,"
5134 " check(false, count, expected);"
5137 " check(true, count, expected);"
5140 " return CThrowCountDown(count - 1, jsInterval, cInterval, expected);"
5143 Local<Function> fun =
5144 Local<Function>::Cast(context->Global()->Get(v8_str("JSThrowCountDown")));
5147 // count jsInterval cInterval expected
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);
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);
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);
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);
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);
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);
5175 void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
5176 ApiTestFuzzer::Fuzz();
5177 CHECK_EQ(1, args.Length());
5178 args.GetIsolate()->ThrowException(args[0]);
5182 THREADED_TEST(ThrowValues) {
5183 v8::Isolate* isolate = CcTest::isolate();
5184 v8::HandleScope scope(isolate);
5185 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5186 templ->Set(v8_str("Throw"), v8::FunctionTemplate::New(isolate, ThrowValue));
5187 LocalContext context(0, templ);
5188 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
5189 "function Run(obj) {"
5195 " return 'no exception';"
5197 "[Run('str'), Run(1), Run(0), Run(null), Run(void 0)];"));
5198 CHECK_EQ(5u, result->Length());
5199 CHECK(result->Get(v8::Integer::New(isolate, 0))->IsString());
5200 CHECK(result->Get(v8::Integer::New(isolate, 1))->IsNumber());
5201 CHECK_EQ(1, result->Get(v8::Integer::New(isolate, 1))->Int32Value());
5202 CHECK(result->Get(v8::Integer::New(isolate, 2))->IsNumber());
5203 CHECK_EQ(0, result->Get(v8::Integer::New(isolate, 2))->Int32Value());
5204 CHECK(result->Get(v8::Integer::New(isolate, 3))->IsNull());
5205 CHECK(result->Get(v8::Integer::New(isolate, 4))->IsUndefined());
5209 THREADED_TEST(CatchZero) {
5210 LocalContext context;
5211 v8::HandleScope scope(context->GetIsolate());
5212 v8::TryCatch try_catch(context->GetIsolate());
5213 CHECK(!try_catch.HasCaught());
5214 CompileRun("throw 10");
5215 CHECK(try_catch.HasCaught());
5216 CHECK_EQ(10, try_catch.Exception()->Int32Value());
5218 CHECK(!try_catch.HasCaught());
5219 CompileRun("throw 0");
5220 CHECK(try_catch.HasCaught());
5221 CHECK_EQ(0, try_catch.Exception()->Int32Value());
5225 THREADED_TEST(CatchExceptionFromWith) {
5226 LocalContext context;
5227 v8::HandleScope scope(context->GetIsolate());
5228 v8::TryCatch try_catch(context->GetIsolate());
5229 CHECK(!try_catch.HasCaught());
5230 CompileRun("var o = {}; with (o) { throw 42; }");
5231 CHECK(try_catch.HasCaught());
5235 THREADED_TEST(TryCatchAndFinallyHidingException) {
5236 LocalContext context;
5237 v8::HandleScope scope(context->GetIsolate());
5238 v8::TryCatch try_catch(context->GetIsolate());
5239 CHECK(!try_catch.HasCaught());
5240 CompileRun("function f(k) { try { this[k]; } finally { return 0; } };");
5241 CompileRun("f({toString: function() { throw 42; }});");
5242 CHECK(!try_catch.HasCaught());
5246 void WithTryCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
5247 v8::TryCatch try_catch(args.GetIsolate());
5251 THREADED_TEST(TryCatchAndFinally) {
5252 LocalContext context;
5253 v8::Isolate* isolate = context->GetIsolate();
5254 v8::HandleScope scope(isolate);
5255 context->Global()->Set(
5256 v8_str("native_with_try_catch"),
5257 v8::FunctionTemplate::New(isolate, WithTryCatch)->GetFunction());
5258 v8::TryCatch try_catch(isolate);
5259 CHECK(!try_catch.HasCaught());
5262 " throw new Error('a');\n"
5264 " native_with_try_catch();\n"
5266 CHECK(try_catch.HasCaught());
5270 static void TryCatchNested1Helper(int depth) {
5272 v8::TryCatch try_catch(CcTest::isolate());
5273 try_catch.SetVerbose(true);
5274 TryCatchNested1Helper(depth - 1);
5275 CHECK(try_catch.HasCaught());
5276 try_catch.ReThrow();
5278 CcTest::isolate()->ThrowException(v8_str("E1"));
5283 static void TryCatchNested2Helper(int depth) {
5285 v8::TryCatch try_catch(CcTest::isolate());
5286 try_catch.SetVerbose(true);
5287 TryCatchNested2Helper(depth - 1);
5288 CHECK(try_catch.HasCaught());
5289 try_catch.ReThrow();
5291 CompileRun("throw 'E2';");
5296 TEST(TryCatchNested) {
5297 v8::V8::Initialize();
5298 LocalContext context;
5299 v8::HandleScope scope(context->GetIsolate());
5302 // Test nested try-catch with a native throw in the end.
5303 v8::TryCatch try_catch(context->GetIsolate());
5304 TryCatchNested1Helper(5);
5305 CHECK(try_catch.HasCaught());
5306 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E1"));
5310 // Test nested try-catch with a JavaScript throw in the end.
5311 v8::TryCatch try_catch(context->GetIsolate());
5312 TryCatchNested2Helper(5);
5313 CHECK(try_catch.HasCaught());
5314 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(try_catch.Exception()), "E2"));
5319 void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
5320 CHECK(try_catch->HasCaught());
5321 Handle<Message> message = try_catch->Message();
5322 Handle<Value> resource = message->GetScriptOrigin().ResourceName();
5323 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
5325 strcmp(*v8::String::Utf8Value(message->Get()), "Uncaught Error: a"));
5326 CHECK_EQ(1, message->GetLineNumber());
5327 CHECK_EQ(0, message->GetStartColumn());
5331 void TryCatchMixedNestingHelper(
5332 const v8::FunctionCallbackInfo<v8::Value>& args) {
5333 ApiTestFuzzer::Fuzz();
5334 v8::TryCatch try_catch(args.GetIsolate());
5335 CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
5336 CHECK(try_catch.HasCaught());
5337 TryCatchMixedNestingCheck(&try_catch);
5338 try_catch.ReThrow();
5342 // This test ensures that an outer TryCatch in the following situation:
5343 // C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
5344 // does not clobber the Message object generated for the inner TryCatch.
5345 // This exercises the ability of TryCatch.ReThrow() to restore the
5346 // inner pending Message before throwing the exception again.
5347 TEST(TryCatchMixedNesting) {
5348 v8::Isolate* isolate = CcTest::isolate();
5349 v8::HandleScope scope(isolate);
5350 v8::V8::Initialize();
5351 v8::TryCatch try_catch(isolate);
5352 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5353 templ->Set(v8_str("TryCatchMixedNestingHelper"),
5354 v8::FunctionTemplate::New(isolate, TryCatchMixedNestingHelper));
5355 LocalContext context(0, templ);
5356 CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
5357 TryCatchMixedNestingCheck(&try_catch);
5361 void TryCatchNativeHelper(const v8::FunctionCallbackInfo<v8::Value>& args) {
5362 ApiTestFuzzer::Fuzz();
5363 v8::TryCatch try_catch(args.GetIsolate());
5364 args.GetIsolate()->ThrowException(v8_str("boom"));
5365 CHECK(try_catch.HasCaught());
5369 TEST(TryCatchNative) {
5370 v8::Isolate* isolate = CcTest::isolate();
5371 v8::HandleScope scope(isolate);
5372 v8::V8::Initialize();
5373 v8::TryCatch try_catch(isolate);
5374 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5375 templ->Set(v8_str("TryCatchNativeHelper"),
5376 v8::FunctionTemplate::New(isolate, TryCatchNativeHelper));
5377 LocalContext context(0, templ);
5378 CompileRun("TryCatchNativeHelper();");
5379 CHECK(!try_catch.HasCaught());
5383 void TryCatchNativeResetHelper(
5384 const v8::FunctionCallbackInfo<v8::Value>& args) {
5385 ApiTestFuzzer::Fuzz();
5386 v8::TryCatch try_catch(args.GetIsolate());
5387 args.GetIsolate()->ThrowException(v8_str("boom"));
5388 CHECK(try_catch.HasCaught());
5390 CHECK(!try_catch.HasCaught());
5394 TEST(TryCatchNativeReset) {
5395 v8::Isolate* isolate = CcTest::isolate();
5396 v8::HandleScope scope(isolate);
5397 v8::V8::Initialize();
5398 v8::TryCatch try_catch(isolate);
5399 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5400 templ->Set(v8_str("TryCatchNativeResetHelper"),
5401 v8::FunctionTemplate::New(isolate, TryCatchNativeResetHelper));
5402 LocalContext context(0, templ);
5403 CompileRun("TryCatchNativeResetHelper();");
5404 CHECK(!try_catch.HasCaught());
5408 THREADED_TEST(Equality) {
5409 LocalContext context;
5410 v8::Isolate* isolate = context->GetIsolate();
5411 v8::HandleScope scope(context->GetIsolate());
5412 // Check that equality works at all before relying on CHECK_EQ
5413 CHECK(v8_str("a")->Equals(v8_str("a")));
5414 CHECK(!v8_str("a")->Equals(v8_str("b")));
5416 CHECK(v8_str("a")->Equals(v8_str("a")));
5417 CHECK(!v8_str("a")->Equals(v8_str("b")));
5418 CHECK(v8_num(1)->Equals(v8_num(1)));
5419 CHECK(v8_num(1.00)->Equals(v8_num(1)));
5420 CHECK(!v8_num(1)->Equals(v8_num(2)));
5422 // Assume String is not internalized.
5423 CHECK(v8_str("a")->StrictEquals(v8_str("a")));
5424 CHECK(!v8_str("a")->StrictEquals(v8_str("b")));
5425 CHECK(!v8_str("5")->StrictEquals(v8_num(5)));
5426 CHECK(v8_num(1)->StrictEquals(v8_num(1)));
5427 CHECK(!v8_num(1)->StrictEquals(v8_num(2)));
5428 CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
5429 Local<Value> not_a_number = v8_num(std::numeric_limits<double>::quiet_NaN());
5430 CHECK(!not_a_number->StrictEquals(not_a_number));
5431 CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
5432 CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
5434 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
5435 v8::Persistent<v8::Object> alias(isolate, obj);
5436 CHECK(v8::Local<v8::Object>::New(isolate, alias)->StrictEquals(obj));
5439 CHECK(v8_str("a")->SameValue(v8_str("a")));
5440 CHECK(!v8_str("a")->SameValue(v8_str("b")));
5441 CHECK(!v8_str("5")->SameValue(v8_num(5)));
5442 CHECK(v8_num(1)->SameValue(v8_num(1)));
5443 CHECK(!v8_num(1)->SameValue(v8_num(2)));
5444 CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
5445 CHECK(not_a_number->SameValue(not_a_number));
5446 CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
5447 CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
5451 THREADED_TEST(MultiRun) {
5452 LocalContext context;
5453 v8::HandleScope scope(context->GetIsolate());
5454 Local<Script> script = v8_compile("x");
5455 for (int i = 0; i < 10; i++) script->Run();
5459 static void GetXValue(Local<String> name,
5460 const v8::PropertyCallbackInfo<v8::Value>& info) {
5461 ApiTestFuzzer::Fuzz();
5462 CHECK(info.Data()->Equals(v8_str("donut")));
5463 CHECK(name->Equals(v8_str("x")));
5464 info.GetReturnValue().Set(name);
5468 THREADED_TEST(SimplePropertyRead) {
5469 LocalContext context;
5470 v8::Isolate* isolate = context->GetIsolate();
5471 v8::HandleScope scope(isolate);
5472 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5473 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5474 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5475 Local<Script> script = v8_compile("obj.x");
5476 for (int i = 0; i < 10; i++) {
5477 Local<Value> result = script->Run();
5478 CHECK(result->Equals(v8_str("x")));
5483 THREADED_TEST(DefinePropertyOnAPIAccessor) {
5484 LocalContext context;
5485 v8::Isolate* isolate = context->GetIsolate();
5486 v8::HandleScope scope(isolate);
5487 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5488 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5489 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5491 // Uses getOwnPropertyDescriptor to check the configurable status
5492 Local<Script> script_desc = v8_compile(
5493 "var prop = Object.getOwnPropertyDescriptor( "
5495 "prop.configurable;");
5496 Local<Value> result = script_desc->Run();
5497 CHECK_EQ(result->BooleanValue(), true);
5499 // Redefine get - but still configurable
5500 Local<Script> script_define = v8_compile(
5501 "var desc = { get: function(){return 42; },"
5502 " configurable: true };"
5503 "Object.defineProperty(obj, 'x', desc);"
5505 result = script_define->Run();
5506 CHECK(result->Equals(v8_num(42)));
5508 // Check that the accessor is still configurable
5509 result = script_desc->Run();
5510 CHECK_EQ(result->BooleanValue(), true);
5512 // Redefine to a non-configurable
5513 script_define = v8_compile(
5514 "var desc = { get: function(){return 43; },"
5515 " configurable: false };"
5516 "Object.defineProperty(obj, 'x', desc);"
5518 result = script_define->Run();
5519 CHECK(result->Equals(v8_num(43)));
5520 result = script_desc->Run();
5521 CHECK_EQ(result->BooleanValue(), false);
5523 // Make sure that it is not possible to redefine again
5524 v8::TryCatch try_catch(isolate);
5525 result = script_define->Run();
5526 CHECK(try_catch.HasCaught());
5527 String::Utf8Value exception_value(try_catch.Exception());
5529 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5533 THREADED_TEST(DefinePropertyOnDefineGetterSetter) {
5534 v8::Isolate* isolate = CcTest::isolate();
5535 v8::HandleScope scope(isolate);
5536 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5537 templ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"));
5538 LocalContext context;
5539 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5541 Local<Script> script_desc = v8_compile(
5543 "Object.getOwnPropertyDescriptor( "
5545 "prop.configurable;");
5546 Local<Value> result = script_desc->Run();
5547 CHECK_EQ(result->BooleanValue(), true);
5549 Local<Script> script_define = v8_compile(
5550 "var desc = {get: function(){return 42; },"
5551 " configurable: true };"
5552 "Object.defineProperty(obj, 'x', desc);"
5554 result = script_define->Run();
5555 CHECK(result->Equals(v8_num(42)));
5558 result = script_desc->Run();
5559 CHECK_EQ(result->BooleanValue(), true);
5562 script_define = v8_compile(
5563 "var desc = {get: function(){return 43; },"
5564 " configurable: false };"
5565 "Object.defineProperty(obj, 'x', desc);"
5567 result = script_define->Run();
5568 CHECK(result->Equals(v8_num(43)));
5569 result = script_desc->Run();
5571 CHECK_EQ(result->BooleanValue(), false);
5573 v8::TryCatch try_catch(isolate);
5574 result = script_define->Run();
5575 CHECK(try_catch.HasCaught());
5576 String::Utf8Value exception_value(try_catch.Exception());
5578 strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5582 static v8::Handle<v8::Object> GetGlobalProperty(LocalContext* context,
5584 return v8::Handle<v8::Object>::Cast((*context)->Global()->Get(v8_str(name)));
5588 THREADED_TEST(DefineAPIAccessorOnObject) {
5589 v8::Isolate* isolate = CcTest::isolate();
5590 v8::HandleScope scope(isolate);
5591 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5592 LocalContext context;
5594 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5595 CompileRun("var obj2 = {};");
5597 CHECK(CompileRun("obj1.x")->IsUndefined());
5598 CHECK(CompileRun("obj2.x")->IsUndefined());
5600 CHECK(GetGlobalProperty(&context, "obj1")
5601 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5603 ExpectString("obj1.x", "x");
5604 CHECK(CompileRun("obj2.x")->IsUndefined());
5606 CHECK(GetGlobalProperty(&context, "obj2")
5607 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5609 ExpectString("obj1.x", "x");
5610 ExpectString("obj2.x", "x");
5612 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5613 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5616 "Object.defineProperty(obj1, 'x',"
5617 "{ get: function() { return 'y'; }, configurable: true })");
5619 ExpectString("obj1.x", "y");
5620 ExpectString("obj2.x", "x");
5623 "Object.defineProperty(obj2, 'x',"
5624 "{ get: function() { return 'y'; }, configurable: true })");
5626 ExpectString("obj1.x", "y");
5627 ExpectString("obj2.x", "y");
5629 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5630 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5632 CHECK(GetGlobalProperty(&context, "obj1")
5633 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5634 CHECK(GetGlobalProperty(&context, "obj2")
5635 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5637 ExpectString("obj1.x", "x");
5638 ExpectString("obj2.x", "x");
5640 ExpectTrue("Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5641 ExpectTrue("Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5643 // Define getters/setters, but now make them not configurable.
5645 "Object.defineProperty(obj1, 'x',"
5646 "{ get: function() { return 'z'; }, configurable: false })");
5648 "Object.defineProperty(obj2, 'x',"
5649 "{ get: function() { return 'z'; }, configurable: false })");
5651 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5652 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5654 ExpectString("obj1.x", "z");
5655 ExpectString("obj2.x", "z");
5657 CHECK(!GetGlobalProperty(&context, "obj1")
5658 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5659 CHECK(!GetGlobalProperty(&context, "obj2")
5660 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5662 ExpectString("obj1.x", "z");
5663 ExpectString("obj2.x", "z");
5667 THREADED_TEST(DontDeleteAPIAccessorsCannotBeOverriden) {
5668 v8::Isolate* isolate = CcTest::isolate();
5669 v8::HandleScope scope(isolate);
5670 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5671 LocalContext context;
5673 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5674 CompileRun("var obj2 = {};");
5676 CHECK(GetGlobalProperty(&context, "obj1")
5677 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5678 v8::DEFAULT, v8::DontDelete));
5679 CHECK(GetGlobalProperty(&context, "obj2")
5680 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut"),
5681 v8::DEFAULT, v8::DontDelete));
5683 ExpectString("obj1.x", "x");
5684 ExpectString("obj2.x", "x");
5686 ExpectTrue("!Object.getOwnPropertyDescriptor(obj1, 'x').configurable");
5687 ExpectTrue("!Object.getOwnPropertyDescriptor(obj2, 'x').configurable");
5689 CHECK(!GetGlobalProperty(&context, "obj1")
5690 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5691 CHECK(!GetGlobalProperty(&context, "obj2")
5692 ->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("donut")));
5695 v8::TryCatch try_catch(isolate);
5697 "Object.defineProperty(obj1, 'x',"
5698 "{get: function() { return 'func'; }})");
5699 CHECK(try_catch.HasCaught());
5700 String::Utf8Value exception_value(try_catch.Exception());
5702 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5705 v8::TryCatch try_catch(isolate);
5707 "Object.defineProperty(obj2, 'x',"
5708 "{get: function() { return 'func'; }})");
5709 CHECK(try_catch.HasCaught());
5710 String::Utf8Value exception_value(try_catch.Exception());
5712 0, strcmp(*exception_value, "TypeError: Cannot redefine property: x"));
5717 static void Get239Value(Local<String> name,
5718 const v8::PropertyCallbackInfo<v8::Value>& info) {
5719 ApiTestFuzzer::Fuzz();
5720 CHECK(info.Data()->Equals(v8_str("donut")));
5721 CHECK(name->Equals(v8_str("239")));
5722 info.GetReturnValue().Set(name);
5726 THREADED_TEST(ElementAPIAccessor) {
5727 v8::Isolate* isolate = CcTest::isolate();
5728 v8::HandleScope scope(isolate);
5729 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5730 LocalContext context;
5732 context->Global()->Set(v8_str("obj1"), templ->NewInstance());
5733 CompileRun("var obj2 = {};");
5735 CHECK(GetGlobalProperty(&context, "obj1")
5736 ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5737 CHECK(GetGlobalProperty(&context, "obj2")
5738 ->SetAccessor(v8_str("239"), Get239Value, NULL, v8_str("donut")));
5740 ExpectString("obj1[239]", "239");
5741 ExpectString("obj2[239]", "239");
5742 ExpectString("obj1['239']", "239");
5743 ExpectString("obj2['239']", "239");
5747 v8::Persistent<Value> xValue;
5750 static void SetXValue(Local<String> name, Local<Value> value,
5751 const v8::PropertyCallbackInfo<void>& info) {
5752 CHECK(value->Equals(v8_num(4)));
5753 CHECK(info.Data()->Equals(v8_str("donut")));
5754 CHECK(name->Equals(v8_str("x")));
5755 CHECK(xValue.IsEmpty());
5756 xValue.Reset(info.GetIsolate(), value);
5760 THREADED_TEST(SimplePropertyWrite) {
5761 v8::Isolate* isolate = CcTest::isolate();
5762 v8::HandleScope scope(isolate);
5763 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5764 templ->SetAccessor(v8_str("x"), GetXValue, SetXValue, v8_str("donut"));
5765 LocalContext context;
5766 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5767 Local<Script> script = v8_compile("obj.x = 4");
5768 for (int i = 0; i < 10; i++) {
5769 CHECK(xValue.IsEmpty());
5771 CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5777 THREADED_TEST(SetterOnly) {
5778 v8::Isolate* isolate = CcTest::isolate();
5779 v8::HandleScope scope(isolate);
5780 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5781 templ->SetAccessor(v8_str("x"), NULL, SetXValue, v8_str("donut"));
5782 LocalContext context;
5783 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5784 Local<Script> script = v8_compile("obj.x = 4; obj.x");
5785 for (int i = 0; i < 10; i++) {
5786 CHECK(xValue.IsEmpty());
5788 CHECK(v8_num(4)->Equals(Local<Value>::New(CcTest::isolate(), xValue)));
5794 THREADED_TEST(NoAccessors) {
5795 v8::Isolate* isolate = CcTest::isolate();
5796 v8::HandleScope scope(isolate);
5797 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5798 templ->SetAccessor(v8_str("x"), static_cast<v8::AccessorGetterCallback>(NULL),
5799 NULL, v8_str("donut"));
5800 LocalContext context;
5801 context->Global()->Set(v8_str("obj"), templ->NewInstance());
5802 Local<Script> script = v8_compile("obj.x = 4; obj.x");
5803 for (int i = 0; i < 10; i++) {
5809 THREADED_TEST(MultiContexts) {
5810 v8::Isolate* isolate = CcTest::isolate();
5811 v8::HandleScope scope(isolate);
5812 v8::Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
5813 templ->Set(v8_str("dummy"),
5814 v8::FunctionTemplate::New(isolate, DummyCallHandler));
5816 Local<String> password = v8_str("Password");
5818 // Create an environment
5819 LocalContext context0(0, templ);
5820 context0->SetSecurityToken(password);
5821 v8::Handle<v8::Object> global0 = context0->Global();
5822 global0->Set(v8_str("custom"), v8_num(1234));
5823 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5825 // Create an independent environment
5826 LocalContext context1(0, templ);
5827 context1->SetSecurityToken(password);
5828 v8::Handle<v8::Object> global1 = context1->Global();
5829 global1->Set(v8_str("custom"), v8_num(1234));
5830 CHECK(!global0->Equals(global1));
5831 CHECK_EQ(1234, global0->Get(v8_str("custom"))->Int32Value());
5832 CHECK_EQ(1234, global1->Get(v8_str("custom"))->Int32Value());
5834 // Now create a new context with the old global
5835 LocalContext context2(0, templ, global1);
5836 context2->SetSecurityToken(password);
5837 v8::Handle<v8::Object> global2 = context2->Global();
5838 CHECK(global1->Equals(global2));
5839 CHECK_EQ(0, global1->Get(v8_str("custom"))->Int32Value());
5840 CHECK_EQ(0, global2->Get(v8_str("custom"))->Int32Value());
5844 THREADED_TEST(FunctionPrototypeAcrossContexts) {
5845 // Make sure that functions created by cloning boilerplates cannot
5846 // communicate through their __proto__ field.
5848 v8::HandleScope scope(CcTest::isolate());
5851 v8::Handle<v8::Object> global0 = env0->Global();
5852 v8::Handle<v8::Object> object0 =
5853 global0->Get(v8_str("Object")).As<v8::Object>();
5854 v8::Handle<v8::Object> tostring0 =
5855 object0->Get(v8_str("toString")).As<v8::Object>();
5856 v8::Handle<v8::Object> proto0 =
5857 tostring0->Get(v8_str("__proto__")).As<v8::Object>();
5858 proto0->Set(v8_str("custom"), v8_num(1234));
5861 v8::Handle<v8::Object> global1 = env1->Global();
5862 v8::Handle<v8::Object> object1 =
5863 global1->Get(v8_str("Object")).As<v8::Object>();
5864 v8::Handle<v8::Object> tostring1 =
5865 object1->Get(v8_str("toString")).As<v8::Object>();
5866 v8::Handle<v8::Object> proto1 =
5867 tostring1->Get(v8_str("__proto__")).As<v8::Object>();
5868 CHECK(!proto1->Has(v8_str("custom")));
5872 THREADED_TEST(Regress892105) {
5873 // Make sure that object and array literals created by cloning
5874 // boilerplates cannot communicate through their __proto__
5875 // field. This is rather difficult to check, but we try to add stuff
5876 // to Object.prototype and Array.prototype and create a new
5877 // environment. This should succeed.
5879 v8::HandleScope scope(CcTest::isolate());
5881 Local<String> source = v8_str(
5882 "Object.prototype.obj = 1234;"
5883 "Array.prototype.arr = 4567;"
5887 Local<Script> script0 = v8_compile(source);
5888 CHECK_EQ(8901.0, script0->Run()->NumberValue());
5891 Local<Script> script1 = v8_compile(source);
5892 CHECK_EQ(8901.0, script1->Run()->NumberValue());
5896 THREADED_TEST(UndetectableObject) {
5898 v8::HandleScope scope(env->GetIsolate());
5900 Local<v8::FunctionTemplate> desc =
5901 v8::FunctionTemplate::New(env->GetIsolate());
5902 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
5904 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5905 env->Global()->Set(v8_str("undetectable"), obj);
5907 ExpectString("undetectable.toString()", "[object Object]");
5908 ExpectString("typeof undetectable", "undefined");
5909 ExpectString("typeof(undetectable)", "undefined");
5910 ExpectBoolean("typeof undetectable == 'undefined'", true);
5911 ExpectBoolean("typeof undetectable == 'object'", false);
5912 ExpectBoolean("if (undetectable) { true; } else { false; }", false);
5913 ExpectBoolean("!undetectable", true);
5915 ExpectObject("true&&undetectable", obj);
5916 ExpectBoolean("false&&undetectable", false);
5917 ExpectBoolean("true||undetectable", true);
5918 ExpectObject("false||undetectable", obj);
5920 ExpectObject("undetectable&&true", obj);
5921 ExpectObject("undetectable&&false", obj);
5922 ExpectBoolean("undetectable||true", true);
5923 ExpectBoolean("undetectable||false", false);
5925 ExpectBoolean("undetectable==null", true);
5926 ExpectBoolean("null==undetectable", true);
5927 ExpectBoolean("undetectable==undefined", true);
5928 ExpectBoolean("undefined==undetectable", true);
5929 ExpectBoolean("undetectable==undetectable", true);
5932 ExpectBoolean("undetectable===null", false);
5933 ExpectBoolean("null===undetectable", false);
5934 ExpectBoolean("undetectable===undefined", false);
5935 ExpectBoolean("undefined===undetectable", false);
5936 ExpectBoolean("undetectable===undetectable", true);
5940 THREADED_TEST(VoidLiteral) {
5942 v8::Isolate* isolate = env->GetIsolate();
5943 v8::HandleScope scope(isolate);
5945 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
5946 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
5948 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5949 env->Global()->Set(v8_str("undetectable"), obj);
5951 ExpectBoolean("undefined == void 0", true);
5952 ExpectBoolean("undetectable == void 0", true);
5953 ExpectBoolean("null == void 0", true);
5954 ExpectBoolean("undefined === void 0", true);
5955 ExpectBoolean("undetectable === void 0", false);
5956 ExpectBoolean("null === void 0", false);
5958 ExpectBoolean("void 0 == undefined", true);
5959 ExpectBoolean("void 0 == undetectable", true);
5960 ExpectBoolean("void 0 == null", true);
5961 ExpectBoolean("void 0 === undefined", true);
5962 ExpectBoolean("void 0 === undetectable", false);
5963 ExpectBoolean("void 0 === null", false);
5968 " return x === void 0;"
5970 " return e.toString();"
5973 "ReferenceError: x is not defined");
5977 " return void 0 === x;"
5979 " return e.toString();"
5982 "ReferenceError: x is not defined");
5986 THREADED_TEST(ExtensibleOnUndetectable) {
5988 v8::Isolate* isolate = env->GetIsolate();
5989 v8::HandleScope scope(isolate);
5991 Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate);
5992 desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable
5994 Local<v8::Object> obj = desc->GetFunction()->NewInstance();
5995 env->Global()->Set(v8_str("undetectable"), obj);
5997 Local<String> source = v8_str(
5998 "undetectable.x = 42;"
6001 Local<Script> script = v8_compile(source);
6003 CHECK(v8::Integer::New(isolate, 42)->Equals(script->Run()));
6005 ExpectBoolean("Object.isExtensible(undetectable)", true);
6007 source = v8_str("Object.preventExtensions(undetectable);");
6008 script = v8_compile(source);
6010 ExpectBoolean("Object.isExtensible(undetectable)", false);
6012 source = v8_str("undetectable.y = 2000;");
6013 script = v8_compile(source);
6015 ExpectBoolean("undetectable.y == undefined", true);
6019 // The point of this test is type checking. We run it only so compilers
6020 // don't complain about an unused function.
6021 TEST(PersistentHandles) {
6023 v8::Isolate* isolate = CcTest::isolate();
6024 v8::HandleScope scope(isolate);
6025 Local<String> str = v8_str("foo");
6026 v8::Persistent<String> p_str(isolate, str);
6028 Local<Script> scr = v8_compile("");
6029 v8::Persistent<Script> p_scr(isolate, scr);
6031 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
6032 v8::Persistent<ObjectTemplate> p_templ(isolate, templ);
6037 static void HandleLogDelegator(
6038 const v8::FunctionCallbackInfo<v8::Value>& args) {
6039 ApiTestFuzzer::Fuzz();
6043 THREADED_TEST(GlobalObjectTemplate) {
6044 v8::Isolate* isolate = CcTest::isolate();
6045 v8::HandleScope handle_scope(isolate);
6046 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
6047 global_template->Set(v8_str("JSNI_Log"),
6048 v8::FunctionTemplate::New(isolate, HandleLogDelegator));
6049 v8::Local<Context> context = Context::New(isolate, 0, global_template);
6050 Context::Scope context_scope(context);
6051 CompileRun("JSNI_Log('LOG')");
6055 static const char* kSimpleExtensionSource =
6061 TEST(SimpleExtensions) {
6062 v8::HandleScope handle_scope(CcTest::isolate());
6063 v8::RegisterExtension(new Extension("simpletest", kSimpleExtensionSource));
6064 const char* extension_names[] = {"simpletest"};
6065 v8::ExtensionConfiguration extensions(1, extension_names);
6066 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6067 Context::Scope lock(context);
6068 v8::Handle<Value> result = CompileRun("Foo()");
6069 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6073 static const char* kStackTraceFromExtensionSource =
6075 " throw new Error();"
6082 TEST(StackTraceInExtension) {
6083 v8::HandleScope handle_scope(CcTest::isolate());
6084 v8::RegisterExtension(
6085 new Extension("stacktracetest", kStackTraceFromExtensionSource));
6086 const char* extension_names[] = {"stacktracetest"};
6087 v8::ExtensionConfiguration extensions(1, extension_names);
6088 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6089 Context::Scope lock(context);
6091 "function user() { bar(); }"
6093 "try{ user(); } catch (e) { error = e; }");
6094 CHECK_EQ(-1, CompileRun("error.stack.indexOf('foo')")->Int32Value());
6095 CHECK_EQ(-1, CompileRun("error.stack.indexOf('bar')")->Int32Value());
6096 CHECK_NE(-1, CompileRun("error.stack.indexOf('user')")->Int32Value());
6100 TEST(NullExtensions) {
6101 v8::HandleScope handle_scope(CcTest::isolate());
6102 v8::RegisterExtension(new Extension("nulltest", NULL));
6103 const char* extension_names[] = {"nulltest"};
6104 v8::ExtensionConfiguration extensions(1, extension_names);
6105 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6106 Context::Scope lock(context);
6107 v8::Handle<Value> result = CompileRun("1+3");
6108 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6112 static const char* kEmbeddedExtensionSource =
6113 "function Ret54321(){return 54321;}~~@@$"
6114 "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
6115 static const int kEmbeddedExtensionSourceValidLen = 34;
6118 TEST(ExtensionMissingSourceLength) {
6119 v8::HandleScope handle_scope(CcTest::isolate());
6120 v8::RegisterExtension(
6121 new Extension("srclentest_fail", kEmbeddedExtensionSource));
6122 const char* extension_names[] = {"srclentest_fail"};
6123 v8::ExtensionConfiguration extensions(1, extension_names);
6124 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6125 CHECK(0 == *context);
6129 TEST(ExtensionWithSourceLength) {
6130 for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
6131 source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
6132 v8::HandleScope handle_scope(CcTest::isolate());
6133 i::ScopedVector<char> extension_name(32);
6134 i::SNPrintF(extension_name, "ext #%d", source_len);
6135 v8::RegisterExtension(new Extension(
6136 extension_name.start(), kEmbeddedExtensionSource, 0, 0, source_len));
6137 const char* extension_names[1] = {extension_name.start()};
6138 v8::ExtensionConfiguration extensions(1, extension_names);
6139 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6140 if (source_len == kEmbeddedExtensionSourceValidLen) {
6141 Context::Scope lock(context);
6142 v8::Handle<Value> result = CompileRun("Ret54321()");
6143 CHECK(v8::Integer::New(CcTest::isolate(), 54321)->Equals(result));
6145 // Anything but exactly the right length should fail to compile.
6146 CHECK(0 == *context);
6152 static const char* kEvalExtensionSource1 =
6153 "function UseEval1() {"
6155 " return eval('x');"
6159 static const char* kEvalExtensionSource2 =
6163 " return eval('x');"
6165 " this.UseEval2 = e;"
6169 TEST(UseEvalFromExtension) {
6170 v8::HandleScope handle_scope(CcTest::isolate());
6171 v8::RegisterExtension(new Extension("evaltest1", kEvalExtensionSource1));
6172 v8::RegisterExtension(new Extension("evaltest2", kEvalExtensionSource2));
6173 const char* extension_names[] = {"evaltest1", "evaltest2"};
6174 v8::ExtensionConfiguration extensions(2, extension_names);
6175 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6176 Context::Scope lock(context);
6177 v8::Handle<Value> result = CompileRun("UseEval1()");
6178 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6179 result = CompileRun("UseEval2()");
6180 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6184 static const char* kWithExtensionSource1 =
6185 "function UseWith1() {"
6187 " with({x:87}) { return x; }"
6191 static const char* kWithExtensionSource2 =
6195 " with ({x:87}) { return x; }"
6197 " this.UseWith2 = e;"
6201 TEST(UseWithFromExtension) {
6202 v8::HandleScope handle_scope(CcTest::isolate());
6203 v8::RegisterExtension(new Extension("withtest1", kWithExtensionSource1));
6204 v8::RegisterExtension(new Extension("withtest2", kWithExtensionSource2));
6205 const char* extension_names[] = {"withtest1", "withtest2"};
6206 v8::ExtensionConfiguration extensions(2, extension_names);
6207 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6208 Context::Scope lock(context);
6209 v8::Handle<Value> result = CompileRun("UseWith1()");
6210 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
6211 result = CompileRun("UseWith2()");
6212 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 87)));
6216 TEST(AutoExtensions) {
6217 v8::HandleScope handle_scope(CcTest::isolate());
6218 Extension* extension = new Extension("autotest", kSimpleExtensionSource);
6219 extension->set_auto_enable(true);
6220 v8::RegisterExtension(extension);
6221 v8::Handle<Context> context = Context::New(CcTest::isolate());
6222 Context::Scope lock(context);
6223 v8::Handle<Value> result = CompileRun("Foo()");
6224 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 4)));
6228 static const char* kSyntaxErrorInExtensionSource = "[";
6231 // Test that a syntax error in an extension does not cause a fatal
6232 // error but results in an empty context.
6233 TEST(SyntaxErrorExtensions) {
6234 v8::HandleScope handle_scope(CcTest::isolate());
6235 v8::RegisterExtension(
6236 new Extension("syntaxerror", kSyntaxErrorInExtensionSource));
6237 const char* extension_names[] = {"syntaxerror"};
6238 v8::ExtensionConfiguration extensions(1, extension_names);
6239 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6240 CHECK(context.IsEmpty());
6244 static const char* kExceptionInExtensionSource = "throw 42";
6247 // Test that an exception when installing an extension does not cause
6248 // a fatal error but results in an empty context.
6249 TEST(ExceptionExtensions) {
6250 v8::HandleScope handle_scope(CcTest::isolate());
6251 v8::RegisterExtension(
6252 new Extension("exception", kExceptionInExtensionSource));
6253 const char* extension_names[] = {"exception"};
6254 v8::ExtensionConfiguration extensions(1, extension_names);
6255 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6256 CHECK(context.IsEmpty());
6260 static const char* kNativeCallInExtensionSource =
6261 "function call_runtime_last_index_of(x) {"
6262 " return %StringLastIndexOf(x, 'bob', 10);"
6266 static const char* kNativeCallTest =
6267 "call_runtime_last_index_of('bobbobboellebobboellebobbob');";
6269 // Test that a native runtime calls are supported in extensions.
6270 TEST(NativeCallInExtensions) {
6271 v8::HandleScope handle_scope(CcTest::isolate());
6272 v8::RegisterExtension(
6273 new Extension("nativecall", kNativeCallInExtensionSource));
6274 const char* extension_names[] = {"nativecall"};
6275 v8::ExtensionConfiguration extensions(1, extension_names);
6276 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6277 Context::Scope lock(context);
6278 v8::Handle<Value> result = CompileRun(kNativeCallTest);
6279 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 3)));
6283 class NativeFunctionExtension : public Extension {
6285 NativeFunctionExtension(const char* name, const char* source,
6286 v8::FunctionCallback fun = &Echo)
6287 : Extension(name, source), function_(fun) {}
6289 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6290 v8::Isolate* isolate, v8::Handle<v8::String> name) {
6291 return v8::FunctionTemplate::New(isolate, function_);
6294 static void Echo(const v8::FunctionCallbackInfo<v8::Value>& args) {
6295 if (args.Length() >= 1) args.GetReturnValue().Set(args[0]);
6299 v8::FunctionCallback function_;
6303 TEST(NativeFunctionDeclaration) {
6304 v8::HandleScope handle_scope(CcTest::isolate());
6305 const char* name = "nativedecl";
6306 v8::RegisterExtension(
6307 new NativeFunctionExtension(name, "native function foo();"));
6308 const char* extension_names[] = {name};
6309 v8::ExtensionConfiguration extensions(1, extension_names);
6310 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6311 Context::Scope lock(context);
6312 v8::Handle<Value> result = CompileRun("foo(42);");
6313 CHECK(result->Equals(v8::Integer::New(CcTest::isolate(), 42)));
6317 TEST(NativeFunctionDeclarationError) {
6318 v8::HandleScope handle_scope(CcTest::isolate());
6319 const char* name = "nativedeclerr";
6320 // Syntax error in extension code.
6321 v8::RegisterExtension(
6322 new NativeFunctionExtension(name, "native\nfunction foo();"));
6323 const char* extension_names[] = {name};
6324 v8::ExtensionConfiguration extensions(1, extension_names);
6325 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6326 CHECK(context.IsEmpty());
6330 TEST(NativeFunctionDeclarationErrorEscape) {
6331 v8::HandleScope handle_scope(CcTest::isolate());
6332 const char* name = "nativedeclerresc";
6333 // Syntax error in extension code - escape code in "native" means that
6334 // it's not treated as a keyword.
6335 v8::RegisterExtension(
6336 new NativeFunctionExtension(name, "nativ\\u0065 function foo();"));
6337 const char* extension_names[] = {name};
6338 v8::ExtensionConfiguration extensions(1, extension_names);
6339 v8::Handle<Context> context = Context::New(CcTest::isolate(), &extensions);
6340 CHECK(context.IsEmpty());
6344 static void CheckDependencies(const char* name, const char* expected) {
6345 v8::HandleScope handle_scope(CcTest::isolate());
6346 v8::ExtensionConfiguration config(1, &name);
6347 LocalContext context(&config);
6348 CHECK(String::NewFromUtf8(CcTest::isolate(), expected)
6349 ->Equals(context->Global()->Get(v8_str("loaded"))));
6360 THREADED_TEST(ExtensionDependency) {
6361 static const char* kEDeps[] = {"D"};
6362 v8::RegisterExtension(new Extension("E", "this.loaded += 'E';", 1, kEDeps));
6363 static const char* kDDeps[] = {"B", "C"};
6364 v8::RegisterExtension(new Extension("D", "this.loaded += 'D';", 2, kDDeps));
6365 static const char* kBCDeps[] = {"A"};
6366 v8::RegisterExtension(new Extension("B", "this.loaded += 'B';", 1, kBCDeps));
6367 v8::RegisterExtension(new Extension("C", "this.loaded += 'C';", 1, kBCDeps));
6368 v8::RegisterExtension(new Extension("A", "this.loaded += 'A';"));
6369 CheckDependencies("A", "undefinedA");
6370 CheckDependencies("B", "undefinedAB");
6371 CheckDependencies("C", "undefinedAC");
6372 CheckDependencies("D", "undefinedABCD");
6373 CheckDependencies("E", "undefinedABCDE");
6374 v8::HandleScope handle_scope(CcTest::isolate());
6375 static const char* exts[2] = {"C", "E"};
6376 v8::ExtensionConfiguration config(2, exts);
6377 LocalContext context(&config);
6378 CHECK(v8_str("undefinedACBDE")
6379 ->Equals(context->Global()->Get(v8_str("loaded"))));
6383 static const char* kExtensionTestScript =
6384 "native function A();"
6385 "native function B();"
6386 "native function C();"
6388 " if (i == 0) return A();"
6389 " if (i == 1) return B();"
6390 " if (i == 2) return C();"
6394 static void CallFun(const v8::FunctionCallbackInfo<v8::Value>& args) {
6395 ApiTestFuzzer::Fuzz();
6396 if (args.IsConstructCall()) {
6397 args.This()->Set(v8_str("data"), args.Data());
6398 args.GetReturnValue().SetNull();
6401 args.GetReturnValue().Set(args.Data());
6405 class FunctionExtension : public Extension {
6407 FunctionExtension() : Extension("functiontest", kExtensionTestScript) {}
6408 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
6409 v8::Isolate* isolate, v8::Handle<String> name);
6413 static int lookup_count = 0;
6414 v8::Handle<v8::FunctionTemplate> FunctionExtension::GetNativeFunctionTemplate(
6415 v8::Isolate* isolate, v8::Handle<String> name) {
6417 if (name->Equals(v8_str("A"))) {
6418 return v8::FunctionTemplate::New(isolate, CallFun,
6419 v8::Integer::New(isolate, 8));
6420 } else if (name->Equals(v8_str("B"))) {
6421 return v8::FunctionTemplate::New(isolate, CallFun,
6422 v8::Integer::New(isolate, 7));
6423 } else if (name->Equals(v8_str("C"))) {
6424 return v8::FunctionTemplate::New(isolate, CallFun,
6425 v8::Integer::New(isolate, 6));
6427 return v8::Handle<v8::FunctionTemplate>();
6432 THREADED_TEST(FunctionLookup) {
6433 v8::RegisterExtension(new FunctionExtension());
6434 v8::HandleScope handle_scope(CcTest::isolate());
6435 static const char* exts[1] = {"functiontest"};
6436 v8::ExtensionConfiguration config(1, exts);
6437 LocalContext context(&config);
6438 CHECK_EQ(3, lookup_count);
6439 CHECK(v8::Integer::New(CcTest::isolate(), 8)->Equals(CompileRun("Foo(0)")));
6440 CHECK(v8::Integer::New(CcTest::isolate(), 7)->Equals(CompileRun("Foo(1)")));
6441 CHECK(v8::Integer::New(CcTest::isolate(), 6)->Equals(CompileRun("Foo(2)")));
6445 THREADED_TEST(NativeFunctionConstructCall) {
6446 v8::RegisterExtension(new FunctionExtension());
6447 v8::HandleScope handle_scope(CcTest::isolate());
6448 static const char* exts[1] = {"functiontest"};
6449 v8::ExtensionConfiguration config(1, exts);
6450 LocalContext context(&config);
6451 for (int i = 0; i < 10; i++) {
6452 // Run a few times to ensure that allocation of objects doesn't
6453 // change behavior of a constructor function.
6454 CHECK(v8::Integer::New(CcTest::isolate(), 8)
6455 ->Equals(CompileRun("(new A()).data")));
6456 CHECK(v8::Integer::New(CcTest::isolate(), 7)
6457 ->Equals(CompileRun("(new B()).data")));
6458 CHECK(v8::Integer::New(CcTest::isolate(), 6)
6459 ->Equals(CompileRun("(new C()).data")));
6464 static const char* last_location;
6465 static const char* last_message;
6466 void StoringErrorCallback(const char* location, const char* message) {
6467 if (last_location == NULL) {
6468 last_location = location;
6469 last_message = message;
6474 // ErrorReporting creates a circular extensions configuration and
6475 // tests that the fatal error handler gets called. This renders V8
6476 // unusable and therefore this test cannot be run in parallel.
6477 TEST(ErrorReporting) {
6478 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
6479 static const char* aDeps[] = {"B"};
6480 v8::RegisterExtension(new Extension("A", "", 1, aDeps));
6481 static const char* bDeps[] = {"A"};
6482 v8::RegisterExtension(new Extension("B", "", 1, bDeps));
6483 last_location = NULL;
6484 v8::ExtensionConfiguration config(1, bDeps);
6485 v8::Handle<Context> context = Context::New(CcTest::isolate(), &config);
6486 CHECK(context.IsEmpty());
6487 CHECK(last_location);
6491 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
6492 v8::Handle<Value> data) {
6493 CHECK(message->GetScriptOrigin().ResourceName()->IsUndefined());
6494 CHECK(v8::Undefined(CcTest::isolate())
6495 ->Equals(message->GetScriptOrigin().ResourceName()));
6496 message->GetLineNumber();
6497 message->GetSourceLine();
6501 THREADED_TEST(ErrorWithMissingScriptInfo) {
6502 LocalContext context;
6503 v8::HandleScope scope(context->GetIsolate());
6504 v8::V8::AddMessageListener(MissingScriptInfoMessageListener);
6505 CompileRun("throw Error()");
6506 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener);
6510 struct FlagAndPersistent {
6512 v8::Global<v8::Object> handle;
6516 static void SetFlag(const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6517 data.GetParameter()->flag = true;
6518 data.GetParameter()->handle.Reset();
6522 static void IndependentWeakHandle(bool global_gc, bool interlinked) {
6523 v8::Isolate* iso = CcTest::isolate();
6524 v8::HandleScope scope(iso);
6525 v8::Handle<Context> context = Context::New(iso);
6526 Context::Scope context_scope(context);
6528 FlagAndPersistent object_a, object_b;
6530 intptr_t big_heap_size;
6533 v8::HandleScope handle_scope(iso);
6534 Local<Object> a(v8::Object::New(iso));
6535 Local<Object> b(v8::Object::New(iso));
6536 object_a.handle.Reset(iso, a);
6537 object_b.handle.Reset(iso, b);
6539 a->Set(v8_str("x"), b);
6540 b->Set(v8_str("x"), a);
6543 CcTest::heap()->CollectAllGarbage();
6545 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6547 // We are relying on this creating a big flag array and reserving the space
6549 v8::Handle<Value> big_array = CompileRun("new Array(50000)");
6550 a->Set(v8_str("y"), big_array);
6551 big_heap_size = CcTest::heap()->SizeOfObjects();
6554 object_a.flag = false;
6555 object_b.flag = false;
6556 object_a.handle.SetWeak(&object_a, &SetFlag,
6557 v8::WeakCallbackType::kParameter);
6558 object_b.handle.SetWeak(&object_b, &SetFlag,
6559 v8::WeakCallbackType::kParameter);
6560 CHECK(!object_b.handle.IsIndependent());
6561 object_a.handle.MarkIndependent();
6562 object_b.handle.MarkIndependent();
6563 CHECK(object_b.handle.IsIndependent());
6565 CcTest::heap()->CollectAllGarbage();
6567 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6569 // A single GC should be enough to reclaim the memory, since we are using
6571 CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 200000);
6572 CHECK(object_a.flag);
6573 CHECK(object_b.flag);
6577 TEST(IndependentWeakHandle) {
6578 IndependentWeakHandle(false, false);
6579 IndependentWeakHandle(false, true);
6580 IndependentWeakHandle(true, false);
6581 IndependentWeakHandle(true, true);
6587 explicit Trivial(int x) : x_(x) {}
6589 int x() { return x_; }
6590 void set_x(int x) { x_ = x; }
6599 Trivial2(int x, int y) : y_(y), x_(x) {}
6601 int x() { return x_; }
6602 void set_x(int x) { x_ = x; }
6604 int y() { return y_; }
6605 void set_y(int y) { y_ = y; }
6613 void CheckInternalFields(
6614 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
6615 v8::Persistent<v8::Object>* handle = data.GetParameter();
6617 Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField1());
6618 Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField2());
6619 CHECK_EQ(42, t1->x());
6620 CHECK_EQ(103, t2->x());
6622 t2->set_x(33550336);
6626 void InternalFieldCallback(bool global_gc) {
6628 v8::Isolate* isolate = env->GetIsolate();
6629 v8::HandleScope scope(isolate);
6631 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
6632 Local<v8::ObjectTemplate> instance_templ = templ->InstanceTemplate();
6635 instance_templ->SetInternalFieldCount(2);
6637 v8::HandleScope scope(isolate);
6638 Local<v8::Object> obj = templ->GetFunction()->NewInstance();
6639 v8::Persistent<v8::Object> handle(isolate, obj);
6640 CHECK_EQ(2, obj->InternalFieldCount());
6641 CHECK(obj->GetInternalField(0)->IsUndefined());
6642 t1 = new Trivial(42);
6643 t2 = new Trivial2(103, 9);
6645 obj->SetAlignedPointerInInternalField(0, t1);
6646 t1 = reinterpret_cast<Trivial*>(obj->GetAlignedPointerFromInternalField(0));
6647 CHECK_EQ(42, t1->x());
6649 obj->SetAlignedPointerInInternalField(1, t2);
6651 reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
6652 CHECK_EQ(103, t2->x());
6654 handle.SetWeak<v8::Persistent<v8::Object>>(
6655 &handle, CheckInternalFields, v8::WeakCallbackType::kInternalFields);
6657 handle.MarkIndependent();
6661 CcTest::heap()->CollectAllGarbage();
6663 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6666 CHECK_EQ(1729, t1->x());
6667 CHECK_EQ(33550336, t2->x());
6674 THREADED_TEST(InternalFieldCallback) {
6675 InternalFieldCallback(false);
6676 InternalFieldCallback(true);
6680 static void ResetUseValueAndSetFlag(
6681 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6682 // Blink will reset the handle, and then use the other handle, so they
6683 // can't use the same backing slot.
6684 data.GetParameter()->handle.Reset();
6685 data.GetParameter()->flag = true;
6689 static void ResetWeakHandle(bool global_gc) {
6690 v8::Isolate* iso = CcTest::isolate();
6691 v8::HandleScope scope(iso);
6692 v8::Handle<Context> context = Context::New(iso);
6693 Context::Scope context_scope(context);
6695 FlagAndPersistent object_a, object_b;
6698 v8::HandleScope handle_scope(iso);
6699 Local<Object> a(v8::Object::New(iso));
6700 Local<Object> b(v8::Object::New(iso));
6701 object_a.handle.Reset(iso, a);
6702 object_b.handle.Reset(iso, b);
6704 CcTest::heap()->CollectAllGarbage(
6705 TestHeap::Heap::kAbortIncrementalMarkingMask);
6707 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6711 object_a.flag = false;
6712 object_b.flag = false;
6713 object_a.handle.SetWeak(&object_a, &ResetUseValueAndSetFlag,
6714 v8::WeakCallbackType::kParameter);
6715 object_b.handle.SetWeak(&object_b, &ResetUseValueAndSetFlag,
6716 v8::WeakCallbackType::kParameter);
6718 object_a.handle.MarkIndependent();
6719 object_b.handle.MarkIndependent();
6720 CHECK(object_b.handle.IsIndependent());
6723 CcTest::heap()->CollectAllGarbage(
6724 TestHeap::Heap::kAbortIncrementalMarkingMask);
6726 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
6728 CHECK(object_a.flag);
6729 CHECK(object_b.flag);
6733 THREADED_TEST(ResetWeakHandle) {
6734 ResetWeakHandle(false);
6735 ResetWeakHandle(true);
6739 static void InvokeScavenge() { CcTest::heap()->CollectGarbage(i::NEW_SPACE); }
6742 static void InvokeMarkSweep() { CcTest::heap()->CollectAllGarbage(); }
6745 static void ForceScavenge2(
6746 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6747 data.GetParameter()->flag = true;
6751 static void ForceScavenge1(
6752 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6753 data.GetParameter()->handle.Reset();
6754 data.SetSecondPassCallback(ForceScavenge2);
6758 static void ForceMarkSweep2(
6759 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6760 data.GetParameter()->flag = true;
6764 static void ForceMarkSweep1(
6765 const v8::WeakCallbackInfo<FlagAndPersistent>& data) {
6766 data.GetParameter()->handle.Reset();
6767 data.SetSecondPassCallback(ForceMarkSweep2);
6771 THREADED_TEST(GCFromWeakCallbacks) {
6772 v8::Isolate* isolate = CcTest::isolate();
6773 v8::Locker locker(CcTest::isolate());
6774 v8::HandleScope scope(isolate);
6775 v8::Handle<Context> context = Context::New(isolate);
6776 Context::Scope context_scope(context);
6778 static const int kNumberOfGCTypes = 2;
6779 typedef v8::WeakCallbackInfo<FlagAndPersistent>::Callback Callback;
6780 Callback gc_forcing_callback[kNumberOfGCTypes] = {&ForceScavenge1,
6783 typedef void (*GCInvoker)();
6784 GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep};
6786 for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) {
6787 for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) {
6788 FlagAndPersistent object;
6790 v8::HandleScope handle_scope(isolate);
6791 object.handle.Reset(isolate, v8::Object::New(isolate));
6793 object.flag = false;
6794 object.handle.SetWeak(&object, gc_forcing_callback[inner_gc],
6795 v8::WeakCallbackType::kParameter);
6796 object.handle.MarkIndependent();
6797 invoke_gc[outer_gc]();
6798 EmptyMessageQueues(isolate);
6805 v8::Handle<Function> args_fun;
6808 static void ArgumentsTestCallback(
6809 const v8::FunctionCallbackInfo<v8::Value>& args) {
6810 ApiTestFuzzer::Fuzz();
6811 v8::Isolate* isolate = args.GetIsolate();
6812 CHECK(args_fun->Equals(args.Callee()));
6813 CHECK_EQ(3, args.Length());
6814 CHECK(v8::Integer::New(isolate, 1)->Equals(args[0]));
6815 CHECK(v8::Integer::New(isolate, 2)->Equals(args[1]));
6816 CHECK(v8::Integer::New(isolate, 3)->Equals(args[2]));
6817 CHECK(v8::Undefined(isolate)->Equals(args[3]));
6818 v8::HandleScope scope(args.GetIsolate());
6819 CcTest::heap()->CollectAllGarbage();
6823 THREADED_TEST(Arguments) {
6824 v8::Isolate* isolate = CcTest::isolate();
6825 v8::HandleScope scope(isolate);
6826 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(isolate);
6827 global->Set(v8_str("f"),
6828 v8::FunctionTemplate::New(isolate, ArgumentsTestCallback));
6829 LocalContext context(NULL, global);
6830 args_fun = context->Global()->Get(v8_str("f")).As<Function>();
6831 v8_compile("f(1, 2, 3)")->Run();
6835 static int p_getter_count;
6836 static int p_getter_count2;
6839 static void PGetter(Local<String> name,
6840 const v8::PropertyCallbackInfo<v8::Value>& info) {
6841 ApiTestFuzzer::Fuzz();
6843 v8::Handle<v8::Object> global =
6844 info.GetIsolate()->GetCurrentContext()->Global();
6845 CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6846 if (name->Equals(v8_str("p1"))) {
6847 CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6848 } else if (name->Equals(v8_str("p2"))) {
6849 CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6850 } else if (name->Equals(v8_str("p3"))) {
6851 CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6852 } else if (name->Equals(v8_str("p4"))) {
6853 CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6858 static void RunHolderTest(v8::Handle<v8::ObjectTemplate> obj) {
6859 ApiTestFuzzer::Fuzz();
6860 LocalContext context;
6861 context->Global()->Set(v8_str("o1"), obj->NewInstance());
6863 "o1.__proto__ = { };"
6864 "var o2 = { __proto__: o1 };"
6865 "var o3 = { __proto__: o2 };"
6866 "var o4 = { __proto__: o3 };"
6867 "for (var i = 0; i < 10; i++) o4.p4;"
6868 "for (var i = 0; i < 10; i++) o3.p3;"
6869 "for (var i = 0; i < 10; i++) o2.p2;"
6870 "for (var i = 0; i < 10; i++) o1.p1;");
6874 static void PGetter2(Local<Name> name,
6875 const v8::PropertyCallbackInfo<v8::Value>& info) {
6876 ApiTestFuzzer::Fuzz();
6878 v8::Handle<v8::Object> global =
6879 info.GetIsolate()->GetCurrentContext()->Global();
6880 CHECK(info.Holder()->Equals(global->Get(v8_str("o1"))));
6881 if (name->Equals(v8_str("p1"))) {
6882 CHECK(info.This()->Equals(global->Get(v8_str("o1"))));
6883 } else if (name->Equals(v8_str("p2"))) {
6884 CHECK(info.This()->Equals(global->Get(v8_str("o2"))));
6885 } else if (name->Equals(v8_str("p3"))) {
6886 CHECK(info.This()->Equals(global->Get(v8_str("o3"))));
6887 } else if (name->Equals(v8_str("p4"))) {
6888 CHECK(info.This()->Equals(global->Get(v8_str("o4"))));
6893 THREADED_TEST(GetterHolders) {
6894 v8::Isolate* isolate = CcTest::isolate();
6895 v8::HandleScope scope(isolate);
6896 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6897 obj->SetAccessor(v8_str("p1"), PGetter);
6898 obj->SetAccessor(v8_str("p2"), PGetter);
6899 obj->SetAccessor(v8_str("p3"), PGetter);
6900 obj->SetAccessor(v8_str("p4"), PGetter);
6903 CHECK_EQ(40, p_getter_count);
6907 THREADED_TEST(PreInterceptorHolders) {
6908 v8::Isolate* isolate = CcTest::isolate();
6909 v8::HandleScope scope(isolate);
6910 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
6911 obj->SetHandler(v8::NamedPropertyHandlerConfiguration(PGetter2));
6912 p_getter_count2 = 0;
6914 CHECK_EQ(40, p_getter_count2);
6918 THREADED_TEST(ObjectInstantiation) {
6919 v8::Isolate* isolate = CcTest::isolate();
6920 v8::HandleScope scope(isolate);
6921 v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
6922 templ->SetAccessor(v8_str("t"), PGetter2);
6923 LocalContext context;
6924 context->Global()->Set(v8_str("o"), templ->NewInstance());
6925 for (int i = 0; i < 100; i++) {
6926 v8::HandleScope inner_scope(CcTest::isolate());
6927 v8::Handle<v8::Object> obj = templ->NewInstance();
6928 CHECK(!obj->Equals(context->Global()->Get(v8_str("o"))));
6929 context->Global()->Set(v8_str("o2"), obj);
6930 v8::Handle<Value> value =
6931 CompileRun("o.__proto__ === o2.__proto__");
6932 CHECK(v8::True(isolate)->Equals(value));
6933 context->Global()->Set(v8_str("o"), obj);
6938 static int StrCmp16(uint16_t* a, uint16_t* b) {
6940 if (*a == 0 && *b == 0) return 0;
6941 if (*a != *b) return 0 + *a - *b;
6948 static int StrNCmp16(uint16_t* a, uint16_t* b, int n) {
6950 if (n-- == 0) return 0;
6951 if (*a == 0 && *b == 0) return 0;
6952 if (*a != *b) return 0 + *a - *b;
6959 int GetUtf8Length(Handle<String> str) {
6960 int len = str->Utf8Length();
6962 i::Handle<i::String> istr(v8::Utils::OpenHandle(*str));
6963 i::String::Flatten(istr);
6964 len = str->Utf8Length();
6970 THREADED_TEST(StringWrite) {
6971 LocalContext context;
6972 v8::HandleScope scope(context->GetIsolate());
6973 v8::Handle<String> str = v8_str("abcde");
6974 // abc<Icelandic eth><Unicode snowman>.
6975 v8::Handle<String> str2 = v8_str("abc\303\260\342\230\203");
6976 v8::Handle<String> str3 = v8::String::NewFromUtf8(
6977 context->GetIsolate(), "abc\0def", v8::String::kNormalString, 7);
6978 // "ab" + lead surrogate + "cd" + trail surrogate + "ef"
6979 uint16_t orphans[8] = { 0x61, 0x62, 0xd800, 0x63, 0x64, 0xdc00, 0x65, 0x66 };
6980 v8::Handle<String> orphans_str = v8::String::NewFromTwoByte(
6981 context->GetIsolate(), orphans, v8::String::kNormalString, 8);
6982 // single lead surrogate
6983 uint16_t lead[1] = { 0xd800 };
6984 v8::Handle<String> lead_str = v8::String::NewFromTwoByte(
6985 context->GetIsolate(), lead, v8::String::kNormalString, 1);
6986 // single trail surrogate
6987 uint16_t trail[1] = { 0xdc00 };
6988 v8::Handle<String> trail_str = v8::String::NewFromTwoByte(
6989 context->GetIsolate(), trail, v8::String::kNormalString, 1);
6991 uint16_t pair[2] = { 0xd800, 0xdc00 };
6992 v8::Handle<String> pair_str = v8::String::NewFromTwoByte(
6993 context->GetIsolate(), pair, v8::String::kNormalString, 2);
6994 const int kStride = 4; // Must match stride in for loops in JS below.
6997 "for (var i = 0; i < 0xd800; i += 4) {"
6998 " left = left + String.fromCharCode(i);"
7002 "for (var i = 0; i < 0xd800; i += 4) {"
7003 " right = String.fromCharCode(i) + right;"
7005 v8::Handle<v8::Object> global = context->Global();
7006 Handle<String> left_tree = global->Get(v8_str("left")).As<String>();
7007 Handle<String> right_tree = global->Get(v8_str("right")).As<String>();
7009 CHECK_EQ(5, str2->Length());
7010 CHECK_EQ(0xd800 / kStride, left_tree->Length());
7011 CHECK_EQ(0xd800 / kStride, right_tree->Length());
7014 char utf8buf[0xd800 * 3];
7019 memset(utf8buf, 0x1, 1000);
7020 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7022 CHECK_EQ(5, charlen);
7023 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7025 memset(utf8buf, 0x1, 1000);
7026 len = str2->WriteUtf8(utf8buf, 8, &charlen);
7028 CHECK_EQ(5, charlen);
7029 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203\1", 9));
7031 memset(utf8buf, 0x1, 1000);
7032 len = str2->WriteUtf8(utf8buf, 7, &charlen);
7034 CHECK_EQ(4, charlen);
7035 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7037 memset(utf8buf, 0x1, 1000);
7038 len = str2->WriteUtf8(utf8buf, 6, &charlen);
7040 CHECK_EQ(4, charlen);
7041 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7043 memset(utf8buf, 0x1, 1000);
7044 len = str2->WriteUtf8(utf8buf, 5, &charlen);
7046 CHECK_EQ(4, charlen);
7047 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\1", 5));
7049 memset(utf8buf, 0x1, 1000);
7050 len = str2->WriteUtf8(utf8buf, 4, &charlen);
7052 CHECK_EQ(3, charlen);
7053 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7055 memset(utf8buf, 0x1, 1000);
7056 len = str2->WriteUtf8(utf8buf, 3, &charlen);
7058 CHECK_EQ(3, charlen);
7059 CHECK_EQ(0, strncmp(utf8buf, "abc\1", 4));
7061 memset(utf8buf, 0x1, 1000);
7062 len = str2->WriteUtf8(utf8buf, 2, &charlen);
7064 CHECK_EQ(2, charlen);
7065 CHECK_EQ(0, strncmp(utf8buf, "ab\1", 3));
7067 // allow orphan surrogates by default
7068 memset(utf8buf, 0x1, 1000);
7069 len = orphans_str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen);
7071 CHECK_EQ(8, charlen);
7072 CHECK_EQ(0, strcmp(utf8buf, "ab\355\240\200cd\355\260\200ef"));
7074 // replace orphan surrogates with unicode replacement character
7075 memset(utf8buf, 0x1, 1000);
7076 len = orphans_str->WriteUtf8(utf8buf,
7079 String::REPLACE_INVALID_UTF8);
7081 CHECK_EQ(8, charlen);
7082 CHECK_EQ(0, strcmp(utf8buf, "ab\357\277\275cd\357\277\275ef"));
7084 // replace single lead surrogate with unicode replacement character
7085 memset(utf8buf, 0x1, 1000);
7086 len = lead_str->WriteUtf8(utf8buf,
7089 String::REPLACE_INVALID_UTF8);
7091 CHECK_EQ(1, charlen);
7092 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7094 // replace single trail surrogate with unicode replacement character
7095 memset(utf8buf, 0x1, 1000);
7096 len = trail_str->WriteUtf8(utf8buf,
7099 String::REPLACE_INVALID_UTF8);
7101 CHECK_EQ(1, charlen);
7102 CHECK_EQ(0, strcmp(utf8buf, "\357\277\275"));
7104 // do not replace / write anything if surrogate pair does not fit the buffer
7106 memset(utf8buf, 0x1, 1000);
7107 len = pair_str->WriteUtf8(utf8buf,
7110 String::REPLACE_INVALID_UTF8);
7112 CHECK_EQ(0, charlen);
7114 memset(utf8buf, 0x1, sizeof(utf8buf));
7115 len = GetUtf8Length(left_tree);
7117 (0x80 + (0x800 - 0x80) * 2 + (0xd800 - 0x800) * 3) / kStride;
7118 CHECK_EQ(utf8_expected, len);
7119 len = left_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7120 CHECK_EQ(utf8_expected, len);
7121 CHECK_EQ(0xd800 / kStride, charlen);
7122 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[utf8_expected - 3]));
7123 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[utf8_expected - 2]));
7124 CHECK_EQ(0xc0 - kStride,
7125 static_cast<unsigned char>(utf8buf[utf8_expected - 1]));
7126 CHECK_EQ(1, utf8buf[utf8_expected]);
7128 memset(utf8buf, 0x1, sizeof(utf8buf));
7129 len = GetUtf8Length(right_tree);
7130 CHECK_EQ(utf8_expected, len);
7131 len = right_tree->WriteUtf8(utf8buf, utf8_expected, &charlen);
7132 CHECK_EQ(utf8_expected, len);
7133 CHECK_EQ(0xd800 / kStride, charlen);
7134 CHECK_EQ(0xed, static_cast<unsigned char>(utf8buf[0]));
7135 CHECK_EQ(0x9f, static_cast<unsigned char>(utf8buf[1]));
7136 CHECK_EQ(0xc0 - kStride, static_cast<unsigned char>(utf8buf[2]));
7137 CHECK_EQ(1, utf8buf[utf8_expected]);
7139 memset(buf, 0x1, sizeof(buf));
7140 memset(wbuf, 0x1, sizeof(wbuf));
7141 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7143 len = str->Write(wbuf);
7145 CHECK_EQ(0, strcmp("abcde", buf));
7146 uint16_t answer1[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7147 CHECK_EQ(0, StrCmp16(answer1, wbuf));
7149 memset(buf, 0x1, sizeof(buf));
7150 memset(wbuf, 0x1, sizeof(wbuf));
7151 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 4);
7153 len = str->Write(wbuf, 0, 4);
7155 CHECK_EQ(0, strncmp("abcd\1", buf, 5));
7156 uint16_t answer2[] = {'a', 'b', 'c', 'd', 0x101};
7157 CHECK_EQ(0, StrNCmp16(answer2, wbuf, 5));
7159 memset(buf, 0x1, sizeof(buf));
7160 memset(wbuf, 0x1, sizeof(wbuf));
7161 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 5);
7163 len = str->Write(wbuf, 0, 5);
7165 CHECK_EQ(0, strncmp("abcde\1", buf, 6));
7166 uint16_t answer3[] = {'a', 'b', 'c', 'd', 'e', 0x101};
7167 CHECK_EQ(0, StrNCmp16(answer3, wbuf, 6));
7169 memset(buf, 0x1, sizeof(buf));
7170 memset(wbuf, 0x1, sizeof(wbuf));
7171 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 0, 6);
7173 len = str->Write(wbuf, 0, 6);
7175 CHECK_EQ(0, strcmp("abcde", buf));
7176 uint16_t answer4[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7177 CHECK_EQ(0, StrCmp16(answer4, wbuf));
7179 memset(buf, 0x1, sizeof(buf));
7180 memset(wbuf, 0x1, sizeof(wbuf));
7181 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, -1);
7183 len = str->Write(wbuf, 4, -1);
7185 CHECK_EQ(0, strcmp("e", buf));
7186 uint16_t answer5[] = {'e', '\0'};
7187 CHECK_EQ(0, StrCmp16(answer5, wbuf));
7189 memset(buf, 0x1, sizeof(buf));
7190 memset(wbuf, 0x1, sizeof(wbuf));
7191 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 6);
7193 len = str->Write(wbuf, 4, 6);
7195 CHECK_EQ(0, strcmp("e", buf));
7196 CHECK_EQ(0, StrCmp16(answer5, wbuf));
7198 memset(buf, 0x1, sizeof(buf));
7199 memset(wbuf, 0x1, sizeof(wbuf));
7200 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 4, 1);
7202 len = str->Write(wbuf, 4, 1);
7204 CHECK_EQ(0, strncmp("e\1", buf, 2));
7205 uint16_t answer6[] = {'e', 0x101};
7206 CHECK_EQ(0, StrNCmp16(answer6, wbuf, 2));
7208 memset(buf, 0x1, sizeof(buf));
7209 memset(wbuf, 0x1, sizeof(wbuf));
7210 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf), 3, 1);
7212 len = str->Write(wbuf, 3, 1);
7214 CHECK_EQ(0, strncmp("d\1", buf, 2));
7215 uint16_t answer7[] = {'d', 0x101};
7216 CHECK_EQ(0, StrNCmp16(answer7, wbuf, 2));
7218 memset(wbuf, 0x1, sizeof(wbuf));
7220 len = str->Write(wbuf, 0, 6, String::NO_NULL_TERMINATION);
7222 CHECK_EQ('X', wbuf[5]);
7223 uint16_t answer8a[] = {'a', 'b', 'c', 'd', 'e'};
7224 uint16_t answer8b[] = {'a', 'b', 'c', 'd', 'e', '\0'};
7225 CHECK_EQ(0, StrNCmp16(answer8a, wbuf, 5));
7226 CHECK_NE(0, StrCmp16(answer8b, wbuf));
7228 CHECK_EQ(0, StrCmp16(answer8b, wbuf));
7230 memset(buf, 0x1, sizeof(buf));
7232 len = str->WriteOneByte(reinterpret_cast<uint8_t*>(buf),
7235 String::NO_NULL_TERMINATION);
7237 CHECK_EQ('X', buf[5]);
7238 CHECK_EQ(0, strncmp("abcde", buf, 5));
7239 CHECK_NE(0, strcmp("abcde", buf));
7241 CHECK_EQ(0, strcmp("abcde", buf));
7243 memset(utf8buf, 0x1, sizeof(utf8buf));
7245 len = str2->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7246 String::NO_NULL_TERMINATION);
7248 CHECK_EQ('X', utf8buf[8]);
7249 CHECK_EQ(5, charlen);
7250 CHECK_EQ(0, strncmp(utf8buf, "abc\303\260\342\230\203", 8));
7251 CHECK_NE(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7253 CHECK_EQ(0, strcmp(utf8buf, "abc\303\260\342\230\203"));
7255 memset(utf8buf, 0x1, sizeof(utf8buf));
7257 len = str->WriteUtf8(utf8buf, sizeof(utf8buf), &charlen,
7258 String::NO_NULL_TERMINATION);
7260 CHECK_EQ('X', utf8buf[5]); // Test that the sixth character is untouched.
7261 CHECK_EQ(5, charlen);
7263 CHECK_EQ(0, strcmp(utf8buf, "abcde"));
7265 memset(buf, 0x1, sizeof(buf));
7266 len = str3->WriteOneByte(reinterpret_cast<uint8_t*>(buf));
7268 CHECK_EQ(0, strcmp("abc", buf));
7269 CHECK_EQ(0, buf[3]);
7270 CHECK_EQ(0, strcmp("def", buf + 4));
7272 CHECK_EQ(0, str->WriteOneByte(NULL, 0, 0, String::NO_NULL_TERMINATION));
7273 CHECK_EQ(0, str->WriteUtf8(NULL, 0, 0, String::NO_NULL_TERMINATION));
7274 CHECK_EQ(0, str->Write(NULL, 0, 0, String::NO_NULL_TERMINATION));
7278 static void Utf16Helper(
7279 LocalContext& context, // NOLINT
7281 const char* lengths_name,
7283 Local<v8::Array> a =
7284 Local<v8::Array>::Cast(context->Global()->Get(v8_str(name)));
7285 Local<v8::Array> alens =
7286 Local<v8::Array>::Cast(context->Global()->Get(v8_str(lengths_name)));
7287 for (int i = 0; i < len; i++) {
7288 Local<v8::String> string =
7289 Local<v8::String>::Cast(a->Get(i));
7290 Local<v8::Number> expected_len =
7291 Local<v8::Number>::Cast(alens->Get(i));
7292 int length = GetUtf8Length(string);
7293 CHECK_EQ(static_cast<int>(expected_len->Value()), length);
7298 THREADED_TEST(Utf16) {
7299 LocalContext context;
7300 v8::HandleScope scope(context->GetIsolate());
7302 "var pad = '01234567890123456789';"
7304 "var plens = [20, 3, 3];"
7305 "p.push('01234567890123456789');"
7306 "var lead = 0xd800;"
7307 "var trail = 0xdc00;"
7308 "p.push(String.fromCharCode(0xd800));"
7309 "p.push(String.fromCharCode(0xdc00));"
7314 "for (var i = 0; i < 3; i++) {"
7315 " p[1] = String.fromCharCode(lead++);"
7316 " for (var j = 0; j < 3; j++) {"
7317 " p[2] = String.fromCharCode(trail++);"
7318 " a.push(p[i] + p[j]);"
7319 " b.push(p[i] + p[j]);"
7320 " c.push(p[i] + p[j]);"
7321 " alens.push(plens[i] + plens[j]);"
7324 "alens[5] -= 2;" // Here the surrogate pairs match up.
7329 "for (var m = 0; m < 9; m++) {"
7330 " for (var n = 0; n < 9; n++) {"
7331 " a2.push(a[m] + a[n]);"
7332 " b2.push(b[m] + b[n]);"
7333 " var newc = 'x' + c[m] + c[n] + 'y';"
7334 " c2.push(newc.substring(1, newc.length - 1));"
7335 " var utf = alens[m] + alens[n];" // And here.
7336 // The 'n's that start with 0xdc.. are 6-8
7337 // The 'm's that end with 0xd8.. are 1, 4 and 7
7338 " if ((m % 3) == 1 && n >= 6) utf -= 2;"
7339 " a2lens.push(utf);"
7342 Utf16Helper(context, "a", "alens", 9);
7343 Utf16Helper(context, "a2", "a2lens", 81);
7347 static bool SameSymbol(Handle<String> s1, Handle<String> s2) {
7348 i::Handle<i::String> is1(v8::Utils::OpenHandle(*s1));
7349 i::Handle<i::String> is2(v8::Utils::OpenHandle(*s2));
7350 return *is1 == *is2;
7354 THREADED_TEST(Utf16Symbol) {
7355 LocalContext context;
7356 v8::HandleScope scope(context->GetIsolate());
7358 Handle<String> symbol1 = v8::String::NewFromUtf8(
7359 context->GetIsolate(), "abc", v8::String::kInternalizedString);
7360 Handle<String> symbol2 = v8::String::NewFromUtf8(
7361 context->GetIsolate(), "abc", v8::String::kInternalizedString);
7362 CHECK(SameSymbol(symbol1, symbol2));
7365 "var sym0 = 'benedictus';"
7366 "var sym0b = 'S\303\270ren';"
7367 "var sym1 = '\355\240\201\355\260\207';"
7368 "var sym2 = '\360\220\220\210';"
7369 "var sym3 = 'x\355\240\201\355\260\207';"
7370 "var sym4 = 'x\360\220\220\210';"
7371 "if (sym1.length != 2) throw sym1;"
7372 "if (sym1.charCodeAt(1) != 0xdc07) throw sym1.charCodeAt(1);"
7373 "if (sym2.length != 2) throw sym2;"
7374 "if (sym2.charCodeAt(1) != 0xdc08) throw sym2.charCodeAt(2);"
7375 "if (sym3.length != 3) throw sym3;"
7376 "if (sym3.charCodeAt(2) != 0xdc07) throw sym1.charCodeAt(2);"
7377 "if (sym4.length != 3) throw sym4;"
7378 "if (sym4.charCodeAt(2) != 0xdc08) throw sym2.charCodeAt(2);");
7379 Handle<String> sym0 = v8::String::NewFromUtf8(
7380 context->GetIsolate(), "benedictus", v8::String::kInternalizedString);
7381 Handle<String> sym0b = v8::String::NewFromUtf8(
7382 context->GetIsolate(), "S\303\270ren", v8::String::kInternalizedString);
7383 Handle<String> sym1 =
7384 v8::String::NewFromUtf8(context->GetIsolate(), "\355\240\201\355\260\207",
7385 v8::String::kInternalizedString);
7386 Handle<String> sym2 =
7387 v8::String::NewFromUtf8(context->GetIsolate(), "\360\220\220\210",
7388 v8::String::kInternalizedString);
7389 Handle<String> sym3 = v8::String::NewFromUtf8(
7390 context->GetIsolate(), "x\355\240\201\355\260\207",
7391 v8::String::kInternalizedString);
7392 Handle<String> sym4 =
7393 v8::String::NewFromUtf8(context->GetIsolate(), "x\360\220\220\210",
7394 v8::String::kInternalizedString);
7395 v8::Local<v8::Object> global = context->Global();
7396 Local<Value> s0 = global->Get(v8_str("sym0"));
7397 Local<Value> s0b = global->Get(v8_str("sym0b"));
7398 Local<Value> s1 = global->Get(v8_str("sym1"));
7399 Local<Value> s2 = global->Get(v8_str("sym2"));
7400 Local<Value> s3 = global->Get(v8_str("sym3"));
7401 Local<Value> s4 = global->Get(v8_str("sym4"));
7402 CHECK(SameSymbol(sym0, Handle<String>::Cast(s0)));
7403 CHECK(SameSymbol(sym0b, Handle<String>::Cast(s0b)));
7404 CHECK(SameSymbol(sym1, Handle<String>::Cast(s1)));
7405 CHECK(SameSymbol(sym2, Handle<String>::Cast(s2)));
7406 CHECK(SameSymbol(sym3, Handle<String>::Cast(s3)));
7407 CHECK(SameSymbol(sym4, Handle<String>::Cast(s4)));
7411 THREADED_TEST(Utf16MissingTrailing) {
7412 LocalContext context;
7413 v8::HandleScope scope(context->GetIsolate());
7415 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
7416 int size = 1024 * 64;
7417 uint8_t* buffer = new uint8_t[size];
7418 for (int i = 0; i < size; i += 4) {
7420 buffer[i + 1] = 0x9d;
7421 buffer[i + 2] = 0x80;
7422 buffer[i + 3] = 0x9e;
7425 // Now invoke the decoder without last 3 bytes
7426 v8::Local<v8::String> str =
7427 v8::String::NewFromUtf8(
7428 context->GetIsolate(), reinterpret_cast<char*>(buffer),
7429 v8::NewStringType::kNormal, size - 3).ToLocalChecked();
7435 THREADED_TEST(Utf16Trailing3Byte) {
7436 LocalContext context;
7437 v8::HandleScope scope(context->GetIsolate());
7439 // Make sure it will go past the buffer, so it will call `WriteUtf16Slow`
7440 int size = 1024 * 63;
7441 uint8_t* buffer = new uint8_t[size];
7442 for (int i = 0; i < size; i += 3) {
7444 buffer[i + 1] = 0x80;
7445 buffer[i + 2] = 0xa6;
7448 // Now invoke the decoder without last 3 bytes
7449 v8::Local<v8::String> str =
7450 v8::String::NewFromUtf8(
7451 context->GetIsolate(), reinterpret_cast<char*>(buffer),
7452 v8::NewStringType::kNormal, size).ToLocalChecked();
7454 v8::String::Value value(str);
7455 CHECK_EQ(value.length(), size / 3);
7456 CHECK_EQ((*value)[value.length() - 1], 0x2026);
7462 THREADED_TEST(ToArrayIndex) {
7463 LocalContext context;
7464 v8::Isolate* isolate = context->GetIsolate();
7465 v8::HandleScope scope(isolate);
7467 v8::Handle<String> str = v8_str("42");
7468 v8::Handle<v8::Uint32> index = str->ToArrayIndex();
7469 CHECK(!index.IsEmpty());
7470 CHECK_EQ(42.0, index->Uint32Value());
7471 str = v8_str("42asdf");
7472 index = str->ToArrayIndex();
7473 CHECK(index.IsEmpty());
7474 str = v8_str("-42");
7475 index = str->ToArrayIndex();
7476 CHECK(index.IsEmpty());
7477 str = v8_str("4294967294");
7478 index = str->ToArrayIndex();
7479 CHECK(!index.IsEmpty());
7480 CHECK_EQ(4294967294.0, index->Uint32Value());
7481 v8::Handle<v8::Number> num = v8::Number::New(isolate, 1);
7482 index = num->ToArrayIndex();
7483 CHECK(!index.IsEmpty());
7484 CHECK_EQ(1.0, index->Uint32Value());
7485 num = v8::Number::New(isolate, -1);
7486 index = num->ToArrayIndex();
7487 CHECK(index.IsEmpty());
7488 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
7489 index = obj->ToArrayIndex();
7490 CHECK(index.IsEmpty());
7494 THREADED_TEST(ErrorConstruction) {
7495 LocalContext context;
7496 v8::HandleScope scope(context->GetIsolate());
7498 v8::Handle<String> foo = v8_str("foo");
7499 v8::Handle<String> message = v8_str("message");
7500 v8::Handle<Value> range_error = v8::Exception::RangeError(foo);
7501 CHECK(range_error->IsObject());
7502 CHECK(range_error.As<v8::Object>()->Get(message)->Equals(foo));
7503 v8::Handle<Value> reference_error = v8::Exception::ReferenceError(foo);
7504 CHECK(reference_error->IsObject());
7505 CHECK(reference_error.As<v8::Object>()->Get(message)->Equals(foo));
7506 v8::Handle<Value> syntax_error = v8::Exception::SyntaxError(foo);
7507 CHECK(syntax_error->IsObject());
7508 CHECK(syntax_error.As<v8::Object>()->Get(message)->Equals(foo));
7509 v8::Handle<Value> type_error = v8::Exception::TypeError(foo);
7510 CHECK(type_error->IsObject());
7511 CHECK(type_error.As<v8::Object>()->Get(message)->Equals(foo));
7512 v8::Handle<Value> error = v8::Exception::Error(foo);
7513 CHECK(error->IsObject());
7514 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7518 static void ThrowV8Exception(const v8::FunctionCallbackInfo<v8::Value>& info) {
7519 ApiTestFuzzer::Fuzz();
7520 v8::Handle<String> foo = v8_str("foo");
7521 v8::Handle<String> message = v8_str("message");
7522 v8::Handle<Value> error = v8::Exception::Error(foo);
7523 CHECK(error->IsObject());
7524 CHECK(error.As<v8::Object>()->Get(message)->Equals(foo));
7525 info.GetIsolate()->ThrowException(error);
7526 info.GetReturnValue().SetUndefined();
7530 THREADED_TEST(ExceptionCreateMessage) {
7531 LocalContext context;
7532 v8::HandleScope scope(context->GetIsolate());
7533 v8::Handle<String> foo_str = v8_str("foo");
7534 v8::Handle<String> message_str = v8_str("message");
7536 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
7538 Local<v8::FunctionTemplate> fun =
7539 v8::FunctionTemplate::New(context->GetIsolate(), ThrowV8Exception);
7540 v8::Local<v8::Object> global = context->Global();
7541 global->Set(v8_str("throwV8Exception"), fun->GetFunction());
7543 TryCatch try_catch(context->GetIsolate());
7546 " throwV8Exception();\n"
7549 CHECK(try_catch.HasCaught());
7551 v8::Handle<v8::Value> error = try_catch.Exception();
7552 CHECK(error->IsObject());
7553 CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7555 v8::Handle<v8::Message> message = v8::Exception::CreateMessage(error);
7556 CHECK(!message.IsEmpty());
7557 CHECK_EQ(2, message->GetLineNumber());
7558 CHECK_EQ(2, message->GetStartColumn());
7560 v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace();
7561 CHECK(!stackTrace.IsEmpty());
7562 CHECK_EQ(2, stackTrace->GetFrameCount());
7564 stackTrace = v8::Exception::GetStackTrace(error);
7565 CHECK(!stackTrace.IsEmpty());
7566 CHECK_EQ(2, stackTrace->GetFrameCount());
7568 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
7570 // Now check message location when SetCaptureStackTraceForUncaughtExceptions
7576 " return throwV8Exception();\n"
7579 CHECK(try_catch.HasCaught());
7581 error = try_catch.Exception();
7582 CHECK(error->IsObject());
7583 CHECK(error.As<v8::Object>()->Get(message_str)->Equals(foo_str));
7585 message = v8::Exception::CreateMessage(error);
7586 CHECK(!message.IsEmpty());
7587 CHECK_EQ(2, message->GetLineNumber());
7588 CHECK_EQ(9, message->GetStartColumn());
7590 // Should be empty stack trace.
7591 stackTrace = message->GetStackTrace();
7592 CHECK(stackTrace.IsEmpty());
7593 CHECK(v8::Exception::GetStackTrace(error).IsEmpty());
7597 THREADED_TEST(ExceptionCreateMessageLength) {
7598 LocalContext context;
7599 v8::HandleScope scope(context->GetIsolate());
7601 // Test that the message is not truncated.
7602 TryCatch try_catch(context->GetIsolate());
7604 "var message = 'm';"
7605 "while (message.length < 1000) message += message;"
7607 CHECK(try_catch.HasCaught());
7609 CHECK_LT(1000, try_catch.Message()->Get()->Length());
7613 static void YGetter(Local<String> name,
7614 const v8::PropertyCallbackInfo<v8::Value>& info) {
7615 ApiTestFuzzer::Fuzz();
7616 info.GetReturnValue().Set(v8_num(10));
7620 static void YSetter(Local<String> name,
7622 const v8::PropertyCallbackInfo<void>& info) {
7623 Local<Object> this_obj = Local<Object>::Cast(info.This());
7624 if (this_obj->Has(name)) this_obj->Delete(name);
7625 this_obj->Set(name, value);
7629 THREADED_TEST(DeleteAccessor) {
7630 v8::Isolate* isolate = CcTest::isolate();
7631 v8::HandleScope scope(isolate);
7632 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(isolate);
7633 obj->SetAccessor(v8_str("y"), YGetter, YSetter);
7634 LocalContext context;
7635 v8::Handle<v8::Object> holder = obj->NewInstance();
7636 context->Global()->Set(v8_str("holder"), holder);
7637 v8::Handle<Value> result = CompileRun(
7638 "holder.y = 11; holder.y = 12; holder.y");
7639 CHECK_EQ(12u, result->Uint32Value());
7643 THREADED_TEST(TypeSwitch) {
7644 v8::Isolate* isolate = CcTest::isolate();
7645 v8::HandleScope scope(isolate);
7646 v8::Handle<v8::FunctionTemplate> templ1 = v8::FunctionTemplate::New(isolate);
7647 v8::Handle<v8::FunctionTemplate> templ2 = v8::FunctionTemplate::New(isolate);
7648 v8::Handle<v8::FunctionTemplate> templ3 = v8::FunctionTemplate::New(isolate);
7649 v8::Handle<v8::FunctionTemplate> templs[3] = { templ1, templ2, templ3 };
7650 v8::Handle<v8::TypeSwitch> type_switch = v8::TypeSwitch::New(3, templs);
7651 LocalContext context;
7652 v8::Handle<v8::Object> obj0 = v8::Object::New(isolate);
7653 v8::Handle<v8::Object> obj1 = templ1->GetFunction()->NewInstance();
7654 v8::Handle<v8::Object> obj2 = templ2->GetFunction()->NewInstance();
7655 v8::Handle<v8::Object> obj3 = templ3->GetFunction()->NewInstance();
7656 for (int i = 0; i < 10; i++) {
7657 CHECK_EQ(0, type_switch->match(obj0));
7658 CHECK_EQ(1, type_switch->match(obj1));
7659 CHECK_EQ(2, type_switch->match(obj2));
7660 CHECK_EQ(3, type_switch->match(obj3));
7661 CHECK_EQ(3, type_switch->match(obj3));
7662 CHECK_EQ(2, type_switch->match(obj2));
7663 CHECK_EQ(1, type_switch->match(obj1));
7664 CHECK_EQ(0, type_switch->match(obj0));
7669 static int trouble_nesting = 0;
7670 static void TroubleCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
7671 ApiTestFuzzer::Fuzz();
7674 // Call a JS function that throws an uncaught exception.
7675 Local<v8::Object> arg_this =
7676 args.GetIsolate()->GetCurrentContext()->Global();
7677 Local<Value> trouble_callee = (trouble_nesting == 3) ?
7678 arg_this->Get(v8_str("trouble_callee")) :
7679 arg_this->Get(v8_str("trouble_caller"));
7680 CHECK(trouble_callee->IsFunction());
7681 args.GetReturnValue().Set(
7682 Function::Cast(*trouble_callee)->Call(arg_this, 0, NULL));
7686 static int report_count = 0;
7687 static void ApiUncaughtExceptionTestListener(v8::Handle<v8::Message>,
7688 v8::Handle<Value>) {
7693 // Counts uncaught exceptions, but other tests running in parallel
7694 // also have uncaught exceptions.
7695 TEST(ApiUncaughtException) {
7698 v8::Isolate* isolate = env->GetIsolate();
7699 v8::HandleScope scope(isolate);
7700 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7702 Local<v8::FunctionTemplate> fun =
7703 v8::FunctionTemplate::New(isolate, TroubleCallback);
7704 v8::Local<v8::Object> global = env->Global();
7705 global->Set(v8_str("trouble"), fun->GetFunction());
7708 "function trouble_callee() {"
7712 "function trouble_caller() {"
7715 Local<Value> trouble = global->Get(v8_str("trouble"));
7716 CHECK(trouble->IsFunction());
7717 Local<Value> trouble_callee = global->Get(v8_str("trouble_callee"));
7718 CHECK(trouble_callee->IsFunction());
7719 Local<Value> trouble_caller = global->Get(v8_str("trouble_caller"));
7720 CHECK(trouble_caller->IsFunction());
7721 Function::Cast(*trouble_caller)->Call(global, 0, NULL);
7722 CHECK_EQ(1, report_count);
7723 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7727 TEST(ApiUncaughtExceptionInObjectObserve) {
7728 v8::internal::FLAG_stack_size = 150;
7731 v8::Isolate* isolate = env->GetIsolate();
7732 v8::HandleScope scope(isolate);
7733 v8::V8::AddMessageListener(ApiUncaughtExceptionTestListener);
7736 "var observe_count = 0;"
7737 "function observer1() { ++observe_count; };"
7738 "function observer2() { ++observe_count; };"
7739 "function observer_throws() { throw new Error(); };"
7740 "function stack_overflow() { return (function f(x) { f(x+1); })(0); };"
7741 "Object.observe(obj, observer_throws.bind());"
7742 "Object.observe(obj, observer1);"
7743 "Object.observe(obj, stack_overflow);"
7744 "Object.observe(obj, observer2);"
7745 "Object.observe(obj, observer_throws.bind());"
7746 "obj.foo = 'bar';");
7747 CHECK_EQ(3, report_count);
7748 ExpectInt32("observe_count", 2);
7749 v8::V8::RemoveMessageListeners(ApiUncaughtExceptionTestListener);
7753 static const char* script_resource_name = "ExceptionInNativeScript.js";
7754 static void ExceptionInNativeScriptTestListener(v8::Handle<v8::Message> message,
7755 v8::Handle<Value>) {
7756 v8::Handle<v8::Value> name_val = message->GetScriptOrigin().ResourceName();
7757 CHECK(!name_val.IsEmpty() && name_val->IsString());
7758 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
7759 CHECK_EQ(0, strcmp(script_resource_name, *name));
7760 CHECK_EQ(3, message->GetLineNumber());
7761 v8::String::Utf8Value source_line(message->GetSourceLine());
7762 CHECK_EQ(0, strcmp(" new o.foo();", *source_line));
7766 TEST(ExceptionInNativeScript) {
7768 v8::Isolate* isolate = env->GetIsolate();
7769 v8::HandleScope scope(isolate);
7770 v8::V8::AddMessageListener(ExceptionInNativeScriptTestListener);
7772 Local<v8::FunctionTemplate> fun =
7773 v8::FunctionTemplate::New(isolate, TroubleCallback);
7774 v8::Local<v8::Object> global = env->Global();
7775 global->Set(v8_str("trouble"), fun->GetFunction());
7777 CompileRunWithOrigin(
7778 "function trouble() {\n"
7782 script_resource_name);
7783 Local<Value> trouble = global->Get(v8_str("trouble"));
7784 CHECK(trouble->IsFunction());
7785 Function::Cast(*trouble)->Call(global, 0, NULL);
7786 v8::V8::RemoveMessageListeners(ExceptionInNativeScriptTestListener);
7790 TEST(CompilationErrorUsingTryCatchHandler) {
7792 v8::HandleScope scope(env->GetIsolate());
7793 v8::TryCatch try_catch(env->GetIsolate());
7794 v8_compile("This doesn't &*&@#$&*^ compile.");
7795 CHECK(*try_catch.Exception());
7796 CHECK(try_catch.HasCaught());
7800 TEST(TryCatchFinallyUsingTryCatchHandler) {
7802 v8::HandleScope scope(env->GetIsolate());
7803 v8::TryCatch try_catch(env->GetIsolate());
7804 CompileRun("try { throw ''; } catch (e) {}");
7805 CHECK(!try_catch.HasCaught());
7806 CompileRun("try { throw ''; } finally {}");
7807 CHECK(try_catch.HasCaught());
7811 "try { throw ''; } finally { return; }"
7813 CHECK(!try_catch.HasCaught());
7816 " { try { throw ''; } finally { throw 0; }"
7818 CHECK(try_catch.HasCaught());
7822 void CEvaluate(const v8::FunctionCallbackInfo<v8::Value>& args) {
7823 v8::HandleScope scope(args.GetIsolate());
7824 CompileRun(args[0]->ToString(args.GetIsolate()));
7828 TEST(TryCatchFinallyStoresMessageUsingTryCatchHandler) {
7829 v8::Isolate* isolate = CcTest::isolate();
7830 v8::HandleScope scope(isolate);
7831 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
7832 templ->Set(v8_str("CEvaluate"),
7833 v8::FunctionTemplate::New(isolate, CEvaluate));
7834 LocalContext context(0, templ);
7835 v8::TryCatch try_catch(isolate);
7837 " CEvaluate('throw 1;');"
7840 CHECK(try_catch.HasCaught());
7841 CHECK(!try_catch.Message().IsEmpty());
7842 String::Utf8Value exception_value(try_catch.Exception());
7843 CHECK_EQ(0, strcmp(*exception_value, "1"));
7846 " CEvaluate('throw 1;');"
7850 CHECK(try_catch.HasCaught());
7851 CHECK(!try_catch.Message().IsEmpty());
7852 String::Utf8Value finally_exception_value(try_catch.Exception());
7853 CHECK_EQ(0, strcmp(*finally_exception_value, "2"));
7857 // For use within the TestSecurityHandler() test.
7858 static bool g_security_callback_result = false;
7859 static bool SecurityTestCallback(Local<v8::Object> global, Local<Value> name,
7860 v8::AccessType type, Local<Value> data) {
7862 return g_security_callback_result;
7866 // SecurityHandler can't be run twice
7867 TEST(SecurityHandler) {
7868 v8::Isolate* isolate = CcTest::isolate();
7869 v8::HandleScope scope0(isolate);
7870 v8::Handle<v8::ObjectTemplate> global_template =
7871 v8::ObjectTemplate::New(isolate);
7872 global_template->SetAccessCheckCallbacks(SecurityTestCallback, NULL);
7873 // Create an environment
7874 v8::Handle<Context> context0 = Context::New(isolate, NULL, global_template);
7877 v8::Handle<v8::Object> global0 = context0->Global();
7878 v8::Handle<Script> script0 = v8_compile("foo = 111");
7880 global0->Set(v8_str("0"), v8_num(999));
7881 v8::Handle<Value> foo0 = global0->Get(v8_str("foo"));
7882 CHECK_EQ(111, foo0->Int32Value());
7883 v8::Handle<Value> z0 = global0->Get(v8_str("0"));
7884 CHECK_EQ(999, z0->Int32Value());
7886 // Create another environment, should fail security checks.
7887 v8::HandleScope scope1(isolate);
7889 v8::Handle<Context> context1 =
7890 Context::New(isolate, NULL, global_template);
7893 v8::Handle<v8::Object> global1 = context1->Global();
7894 global1->Set(v8_str("othercontext"), global0);
7895 // This set will fail the security check.
7896 v8::Handle<Script> script1 =
7897 v8_compile("othercontext.foo = 222; othercontext[0] = 888;");
7899 g_security_callback_result = true;
7900 // This read will pass the security check.
7901 v8::Handle<Value> foo1 = global0->Get(v8_str("foo"));
7902 CHECK_EQ(111, foo1->Int32Value());
7903 // This read will pass the security check.
7904 v8::Handle<Value> z1 = global0->Get(v8_str("0"));
7905 CHECK_EQ(999, z1->Int32Value());
7907 // Create another environment, should pass security checks.
7909 v8::HandleScope scope2(isolate);
7910 LocalContext context2;
7911 v8::Handle<v8::Object> global2 = context2->Global();
7912 global2->Set(v8_str("othercontext"), global0);
7913 v8::Handle<Script> script2 =
7914 v8_compile("othercontext.foo = 333; othercontext[0] = 888;");
7916 v8::Handle<Value> foo2 = global0->Get(v8_str("foo"));
7917 CHECK_EQ(333, foo2->Int32Value());
7918 v8::Handle<Value> z2 = global0->Get(v8_str("0"));
7919 CHECK_EQ(888, z2->Int32Value());
7927 THREADED_TEST(SecurityChecks) {
7929 v8::HandleScope handle_scope(env1->GetIsolate());
7930 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
7932 Local<Value> foo = v8_str("foo");
7933 Local<Value> bar = v8_str("bar");
7935 // Set to the same domain.
7936 env1->SetSecurityToken(foo);
7938 // Create a function in env1.
7939 CompileRun("spy=function(){return spy;}");
7940 Local<Value> spy = env1->Global()->Get(v8_str("spy"));
7941 CHECK(spy->IsFunction());
7943 // Create another function accessing global objects.
7944 CompileRun("spy2=function(){return new this.Array();}");
7945 Local<Value> spy2 = env1->Global()->Get(v8_str("spy2"));
7946 CHECK(spy2->IsFunction());
7948 // Switch to env2 in the same domain and invoke spy on env2.
7950 env2->SetSecurityToken(foo);
7952 Context::Scope scope_env2(env2);
7953 Local<Value> result = Function::Cast(*spy)->Call(env2->Global(), 0, NULL);
7954 CHECK(result->IsFunction());
7958 env2->SetSecurityToken(bar);
7959 Context::Scope scope_env2(env2);
7961 // Call cross_domain_call, it should throw an exception
7962 v8::TryCatch try_catch(env1->GetIsolate());
7963 Function::Cast(*spy2)->Call(env2->Global(), 0, NULL);
7964 CHECK(try_catch.HasCaught());
7969 // Regression test case for issue 1183439.
7970 THREADED_TEST(SecurityChecksForPrototypeChain) {
7971 LocalContext current;
7972 v8::HandleScope scope(current->GetIsolate());
7973 v8::Handle<Context> other = Context::New(current->GetIsolate());
7975 // Change context to be able to get to the Object function in the
7976 // other context without hitting the security checks.
7977 v8::Local<Value> other_object;
7978 { Context::Scope scope(other);
7979 other_object = other->Global()->Get(v8_str("Object"));
7980 other->Global()->Set(v8_num(42), v8_num(87));
7983 current->Global()->Set(v8_str("other"), other->Global());
7984 CHECK(v8_compile("other")->Run()->Equals(other->Global()));
7986 // Make sure the security check fails here and we get an undefined
7987 // result instead of getting the Object function. Repeat in a loop
7988 // to make sure to exercise the IC code.
7989 v8::Local<Script> access_other0 = v8_compile("other.Object");
7990 v8::Local<Script> access_other1 = v8_compile("other[42]");
7991 for (int i = 0; i < 5; i++) {
7992 CHECK(access_other0->Run().IsEmpty());
7993 CHECK(access_other1->Run().IsEmpty());
7996 // Create an object that has 'other' in its prototype chain and make
7997 // sure we cannot access the Object function indirectly through
7998 // that. Repeat in a loop to make sure to exercise the IC code.
7999 v8_compile("function F() { };"
8000 "F.prototype = other;"
8001 "var f = new F();")->Run();
8002 v8::Local<Script> access_f0 = v8_compile("f.Object");
8003 v8::Local<Script> access_f1 = v8_compile("f[42]");
8004 for (int j = 0; j < 5; j++) {
8005 CHECK(access_f0->Run().IsEmpty());
8006 CHECK(access_f1->Run().IsEmpty());
8009 // Now it gets hairy: Set the prototype for the other global object
8010 // to be the current global object. The prototype chain for 'f' now
8011 // goes through 'other' but ends up in the current global object.
8012 { Context::Scope scope(other);
8013 other->Global()->Set(v8_str("__proto__"), current->Global());
8015 // Set a named and an index property on the current global
8016 // object. To force the lookup to go through the other global object,
8017 // the properties must not exist in the other global object.
8018 current->Global()->Set(v8_str("foo"), v8_num(100));
8019 current->Global()->Set(v8_num(99), v8_num(101));
8020 // Try to read the properties from f and make sure that the access
8021 // gets stopped by the security checks on the other global object.
8022 Local<Script> access_f2 = v8_compile("f.foo");
8023 Local<Script> access_f3 = v8_compile("f[99]");
8024 for (int k = 0; k < 5; k++) {
8025 CHECK(access_f2->Run().IsEmpty());
8026 CHECK(access_f3->Run().IsEmpty());
8031 static bool security_check_with_gc_called;
8033 static bool SecurityTestCallbackWithGC(Local<v8::Object> global,
8034 Local<v8::Value> name,
8035 v8::AccessType type, Local<Value> data) {
8036 CcTest::heap()->CollectAllGarbage();
8037 security_check_with_gc_called = true;
8042 TEST(SecurityTestGCAllowed) {
8043 v8::Isolate* isolate = CcTest::isolate();
8044 v8::HandleScope handle_scope(isolate);
8045 v8::Handle<v8::ObjectTemplate> object_template =
8046 v8::ObjectTemplate::New(isolate);
8047 object_template->SetAccessCheckCallbacks(SecurityTestCallbackWithGC, NULL);
8049 v8::Handle<Context> context = Context::New(isolate);
8050 v8::Context::Scope context_scope(context);
8052 context->Global()->Set(v8_str("obj"), object_template->NewInstance());
8054 security_check_with_gc_called = false;
8055 CompileRun("obj[0] = new String(1002);");
8056 CHECK(security_check_with_gc_called);
8058 security_check_with_gc_called = false;
8059 CHECK(CompileRun("obj[0]")->ToString(isolate)->Equals(v8_str("1002")));
8060 CHECK(security_check_with_gc_called);
8064 THREADED_TEST(CrossDomainDelete) {
8066 v8::HandleScope handle_scope(env1->GetIsolate());
8067 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8069 Local<Value> foo = v8_str("foo");
8070 Local<Value> bar = v8_str("bar");
8072 // Set to the same domain.
8073 env1->SetSecurityToken(foo);
8074 env2->SetSecurityToken(foo);
8076 env1->Global()->Set(v8_str("prop"), v8_num(3));
8077 env2->Global()->Set(v8_str("env1"), env1->Global());
8079 // Change env2 to a different domain and delete env1.prop.
8080 env2->SetSecurityToken(bar);
8082 Context::Scope scope_env2(env2);
8083 Local<Value> result =
8084 CompileRun("delete env1.prop");
8085 CHECK(result.IsEmpty());
8088 // Check that env1.prop still exists.
8089 Local<Value> v = env1->Global()->Get(v8_str("prop"));
8090 CHECK(v->IsNumber());
8091 CHECK_EQ(3, v->Int32Value());
8095 THREADED_TEST(CrossDomainIsPropertyEnumerable) {
8097 v8::HandleScope handle_scope(env1->GetIsolate());
8098 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8100 Local<Value> foo = v8_str("foo");
8101 Local<Value> bar = v8_str("bar");
8103 // Set to the same domain.
8104 env1->SetSecurityToken(foo);
8105 env2->SetSecurityToken(foo);
8107 env1->Global()->Set(v8_str("prop"), v8_num(3));
8108 env2->Global()->Set(v8_str("env1"), env1->Global());
8110 // env1.prop is enumerable in env2.
8111 Local<String> test = v8_str("propertyIsEnumerable.call(env1, 'prop')");
8113 Context::Scope scope_env2(env2);
8114 Local<Value> result = CompileRun(test);
8115 CHECK(result->IsTrue());
8118 // Change env2 to a different domain and test again.
8119 env2->SetSecurityToken(bar);
8121 Context::Scope scope_env2(env2);
8122 Local<Value> result = CompileRun(test);
8123 CHECK(result.IsEmpty());
8128 THREADED_TEST(CrossDomainFor) {
8130 v8::HandleScope handle_scope(env1->GetIsolate());
8131 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8133 Local<Value> foo = v8_str("foo");
8134 Local<Value> bar = v8_str("bar");
8136 // Set to the same domain.
8137 env1->SetSecurityToken(foo);
8138 env2->SetSecurityToken(foo);
8140 env1->Global()->Set(v8_str("prop"), v8_num(3));
8141 env2->Global()->Set(v8_str("env1"), env1->Global());
8143 // Change env2 to a different domain and set env1's global object
8144 // as the __proto__ of an object in env2 and enumerate properties
8145 // in for-in. It shouldn't enumerate properties on env1's global
8147 env2->SetSecurityToken(bar);
8149 Context::Scope scope_env2(env2);
8150 Local<Value> result = CompileRun(
8153 " for (var p in env1) {"
8154 " if (p == 'prop') return false;"
8161 CHECK(result->IsTrue());
8166 THREADED_TEST(CrossDomainForInOnPrototype) {
8168 v8::HandleScope handle_scope(env1->GetIsolate());
8169 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8171 Local<Value> foo = v8_str("foo");
8172 Local<Value> bar = v8_str("bar");
8174 // Set to the same domain.
8175 env1->SetSecurityToken(foo);
8176 env2->SetSecurityToken(foo);
8178 env1->Global()->Set(v8_str("prop"), v8_num(3));
8179 env2->Global()->Set(v8_str("env1"), env1->Global());
8181 // Change env2 to a different domain and set env1's global object
8182 // as the __proto__ of an object in env2 and enumerate properties
8183 // in for-in. It shouldn't enumerate properties on env1's global
8185 env2->SetSecurityToken(bar);
8187 Context::Scope scope_env2(env2);
8188 Local<Value> result = CompileRun(
8190 " var obj = { '__proto__': env1 };"
8192 " for (var p in obj) {"
8193 " if (p == 'prop') return false;"
8200 CHECK(result->IsTrue());
8205 TEST(ContextDetachGlobal) {
8207 v8::HandleScope handle_scope(env1->GetIsolate());
8208 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8210 Local<v8::Object> global1 = env1->Global();
8212 Local<Value> foo = v8_str("foo");
8214 // Set to the same domain.
8215 env1->SetSecurityToken(foo);
8216 env2->SetSecurityToken(foo);
8221 // Create a function in env2 and add a reference to it in env1.
8222 Local<v8::Object> global2 = env2->Global();
8223 global2->Set(v8_str("prop"), v8::Integer::New(env2->GetIsolate(), 1));
8224 CompileRun("function getProp() {return prop;}");
8226 env1->Global()->Set(v8_str("getProp"),
8227 global2->Get(v8_str("getProp")));
8229 // Detach env2's global, and reuse the global object of env2
8231 env2->DetachGlobal();
8233 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8235 v8::Handle<v8::ObjectTemplate>(),
8237 env3->SetSecurityToken(v8_str("bar"));
8240 Local<v8::Object> global3 = env3->Global();
8241 CHECK(global2->Equals(global3));
8242 CHECK(global3->Get(v8_str("prop"))->IsUndefined());
8243 CHECK(global3->Get(v8_str("getProp"))->IsUndefined());
8244 global3->Set(v8_str("prop"), v8::Integer::New(env3->GetIsolate(), -1));
8245 global3->Set(v8_str("prop2"), v8::Integer::New(env3->GetIsolate(), 2));
8248 // Call getProp in env1, and it should return the value 1
8250 Local<Value> get_prop = global1->Get(v8_str("getProp"));
8251 CHECK(get_prop->IsFunction());
8252 v8::TryCatch try_catch(env1->GetIsolate());
8253 Local<Value> r = Function::Cast(*get_prop)->Call(global1, 0, NULL);
8254 CHECK(!try_catch.HasCaught());
8255 CHECK_EQ(1, r->Int32Value());
8258 // Check that env3 is not accessible from env1
8260 Local<Value> r = global3->Get(v8_str("prop2"));
8266 TEST(DetachGlobal) {
8268 v8::HandleScope scope(env1->GetIsolate());
8270 // Create second environment.
8271 v8::Handle<Context> env2 = Context::New(env1->GetIsolate());
8273 Local<Value> foo = v8_str("foo");
8275 // Set same security token for env1 and env2.
8276 env1->SetSecurityToken(foo);
8277 env2->SetSecurityToken(foo);
8279 // Create a property on the global object in env2.
8281 v8::Context::Scope scope(env2);
8282 env2->Global()->Set(v8_str("p"), v8::Integer::New(env2->GetIsolate(), 42));
8285 // Create a reference to env2 global from env1 global.
8286 env1->Global()->Set(v8_str("other"), env2->Global());
8288 // Check that we have access to other.p in env2 from env1.
8289 Local<Value> result = CompileRun("other.p");
8290 CHECK(result->IsInt32());
8291 CHECK_EQ(42, result->Int32Value());
8293 // Hold on to global from env2 and detach global from env2.
8294 Local<v8::Object> global2 = env2->Global();
8295 env2->DetachGlobal();
8297 // Check that the global has been detached. No other.p property can
8299 result = CompileRun("other.p");
8300 CHECK(result.IsEmpty());
8302 // Reuse global2 for env3.
8303 v8::Handle<Context> env3 = Context::New(env1->GetIsolate(),
8305 v8::Handle<v8::ObjectTemplate>(),
8307 CHECK(global2->Equals(env3->Global()));
8309 // Start by using the same security token for env3 as for env1 and env2.
8310 env3->SetSecurityToken(foo);
8312 // Create a property on the global object in env3.
8314 v8::Context::Scope scope(env3);
8315 env3->Global()->Set(v8_str("p"), v8::Integer::New(env3->GetIsolate(), 24));
8318 // Check that other.p is now the property in env3 and that we have access.
8319 result = CompileRun("other.p");
8320 CHECK(result->IsInt32());
8321 CHECK_EQ(24, result->Int32Value());
8323 // Change security token for env3 to something different from env1 and env2.
8324 env3->SetSecurityToken(v8_str("bar"));
8326 // Check that we do not have access to other.p in env1. |other| is now
8327 // the global object for env3 which has a different security token,
8328 // so access should be blocked.
8329 result = CompileRun("other.p");
8330 CHECK(result.IsEmpty());
8334 void GetThisX(const v8::FunctionCallbackInfo<v8::Value>& info) {
8335 info.GetReturnValue().Set(
8336 info.GetIsolate()->GetCurrentContext()->Global()->Get(v8_str("x")));
8340 TEST(DetachedAccesses) {
8342 v8::HandleScope scope(env1->GetIsolate());
8344 // Create second environment.
8345 Local<ObjectTemplate> inner_global_template =
8346 FunctionTemplate::New(env1->GetIsolate())->InstanceTemplate();
8347 inner_global_template ->SetAccessorProperty(
8348 v8_str("this_x"), FunctionTemplate::New(env1->GetIsolate(), GetThisX));
8349 v8::Local<Context> env2 =
8350 Context::New(env1->GetIsolate(), NULL, inner_global_template);
8352 Local<Value> foo = v8_str("foo");
8354 // Set same security token for env1 and env2.
8355 env1->SetSecurityToken(foo);
8356 env2->SetSecurityToken(foo);
8358 env1->Global()->Set(v8_str("x"), v8_str("env1_x"));
8361 v8::Context::Scope scope(env2);
8362 env2->Global()->Set(v8_str("x"), v8_str("env2_x"));
8364 "function bound_x() { return x; }"
8365 "function get_x() { return this.x; }"
8366 "function get_x_w() { return (function() {return this.x;})(); }");
8367 env1->Global()->Set(v8_str("bound_x"), CompileRun("bound_x"));
8368 env1->Global()->Set(v8_str("get_x"), CompileRun("get_x"));
8369 env1->Global()->Set(v8_str("get_x_w"), CompileRun("get_x_w"));
8370 env1->Global()->Set(
8372 CompileRun("Object.getOwnPropertyDescriptor(this, 'this_x').get"));
8375 Local<Object> env2_global = env2->Global();
8376 env2->DetachGlobal();
8378 Local<Value> result;
8379 result = CompileRun("bound_x()");
8380 CHECK(v8_str("env2_x")->Equals(result));
8381 result = CompileRun("get_x()");
8382 CHECK(result.IsEmpty());
8383 result = CompileRun("get_x_w()");
8384 CHECK(result.IsEmpty());
8385 result = CompileRun("this_x()");
8386 CHECK(v8_str("env2_x")->Equals(result));
8388 // Reattach env2's proxy
8389 env2 = Context::New(env1->GetIsolate(),
8391 v8::Handle<v8::ObjectTemplate>(),
8393 env2->SetSecurityToken(foo);
8395 v8::Context::Scope scope(env2);
8396 env2->Global()->Set(v8_str("x"), v8_str("env3_x"));
8397 env2->Global()->Set(v8_str("env1"), env1->Global());
8398 result = CompileRun(
8400 "for (var i = 0; i < 4; i++ ) {"
8401 " results.push(env1.bound_x());"
8402 " results.push(env1.get_x());"
8403 " results.push(env1.get_x_w());"
8404 " results.push(env1.this_x());"
8407 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8408 CHECK_EQ(16u, results->Length());
8409 for (int i = 0; i < 16; i += 4) {
8410 CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8411 CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8412 CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8413 CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8417 result = CompileRun(
8419 "for (var i = 0; i < 4; i++ ) {"
8420 " results.push(bound_x());"
8421 " results.push(get_x());"
8422 " results.push(get_x_w());"
8423 " results.push(this_x());"
8426 Local<v8::Array> results = Local<v8::Array>::Cast(result);
8427 CHECK_EQ(16u, results->Length());
8428 for (int i = 0; i < 16; i += 4) {
8429 CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8430 CHECK(v8_str("env3_x")->Equals(results->Get(i + 1)));
8431 CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8432 CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8435 result = CompileRun(
8437 "for (var i = 0; i < 4; i++ ) {"
8438 " results.push(this.bound_x());"
8439 " results.push(this.get_x());"
8440 " results.push(this.get_x_w());"
8441 " results.push(this.this_x());"
8444 results = Local<v8::Array>::Cast(result);
8445 CHECK_EQ(16u, results->Length());
8446 for (int i = 0; i < 16; i += 4) {
8447 CHECK(v8_str("env2_x")->Equals(results->Get(i + 0)));
8448 CHECK(v8_str("env1_x")->Equals(results->Get(i + 1)));
8449 CHECK(v8_str("env3_x")->Equals(results->Get(i + 2)));
8450 CHECK(v8_str("env2_x")->Equals(results->Get(i + 3)));
8455 static bool allowed_access = false;
8456 static bool AccessBlocker(Local<v8::Object> global, Local<Value> name,
8457 v8::AccessType type, Local<Value> data) {
8458 return CcTest::isolate()->GetCurrentContext()->Global()->Equals(global) ||
8463 static int g_echo_value = -1;
8466 static void EchoGetter(
8468 const v8::PropertyCallbackInfo<v8::Value>& info) {
8469 info.GetReturnValue().Set(v8_num(g_echo_value));
8473 static void EchoSetter(Local<String> name,
8475 const v8::PropertyCallbackInfo<void>&) {
8476 if (value->IsNumber())
8477 g_echo_value = value->Int32Value();
8481 static void UnreachableGetter(
8483 const v8::PropertyCallbackInfo<v8::Value>& info) {
8484 CHECK(false); // This function should not be called..
8488 static void UnreachableSetter(Local<String>,
8490 const v8::PropertyCallbackInfo<void>&) {
8491 CHECK(false); // This function should nto be called.
8495 static void UnreachableFunction(
8496 const v8::FunctionCallbackInfo<v8::Value>& info) {
8497 CHECK(false); // This function should not be called..
8501 TEST(AccessControl) {
8502 v8::Isolate* isolate = CcTest::isolate();
8503 v8::HandleScope handle_scope(isolate);
8504 v8::Handle<v8::ObjectTemplate> global_template =
8505 v8::ObjectTemplate::New(isolate);
8507 global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
8509 // Add an accessor accessible by cross-domain JS code.
8510 global_template->SetAccessor(
8511 v8_str("accessible_prop"),
8512 EchoGetter, EchoSetter,
8513 v8::Handle<Value>(),
8514 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8517 // Add an accessor that is not accessible by cross-domain JS code.
8518 global_template->SetAccessor(v8_str("blocked_prop"),
8519 UnreachableGetter, UnreachableSetter,
8520 v8::Handle<Value>(),
8523 global_template->SetAccessorProperty(
8524 v8_str("blocked_js_prop"),
8525 v8::FunctionTemplate::New(isolate, UnreachableFunction),
8526 v8::FunctionTemplate::New(isolate, UnreachableFunction),
8530 // Create an environment
8531 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8534 v8::Handle<v8::Object> global0 = context0->Global();
8536 // Define a property with JS getter and setter.
8538 "function getter() { return 'getter'; };\n"
8539 "function setter() { return 'setter'; }\n"
8540 "Object.defineProperty(this, 'js_accessor_p', {get:getter, set:setter})");
8542 Local<Value> getter = global0->Get(v8_str("getter"));
8543 Local<Value> setter = global0->Get(v8_str("setter"));
8545 // And define normal element.
8546 global0->Set(239, v8_str("239"));
8548 // Define an element with JS getter and setter.
8550 "function el_getter() { return 'el_getter'; };\n"
8551 "function el_setter() { return 'el_setter'; };\n"
8552 "Object.defineProperty(this, '42', {get: el_getter, set: el_setter});");
8554 Local<Value> el_getter = global0->Get(v8_str("el_getter"));
8555 Local<Value> el_setter = global0->Get(v8_str("el_setter"));
8557 v8::HandleScope scope1(isolate);
8559 v8::Local<Context> context1 = Context::New(isolate);
8562 v8::Handle<v8::Object> global1 = context1->Global();
8563 global1->Set(v8_str("other"), global0);
8565 // Access blocked property.
8566 CompileRun("other.blocked_prop = 1");
8568 CHECK(CompileRun("other.blocked_prop").IsEmpty());
8569 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8572 CompileRun("propertyIsEnumerable.call(other, 'blocked_prop')").IsEmpty());
8574 // Access blocked element.
8575 CHECK(CompileRun("other[239] = 1").IsEmpty());
8577 CHECK(CompileRun("other[239]").IsEmpty());
8578 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '239')").IsEmpty());
8579 CHECK(CompileRun("propertyIsEnumerable.call(other, '239')").IsEmpty());
8581 allowed_access = true;
8582 // Now we can enumerate the property.
8583 ExpectTrue("propertyIsEnumerable.call(other, '239')");
8584 allowed_access = false;
8586 // Access a property with JS accessor.
8587 CHECK(CompileRun("other.js_accessor_p = 2").IsEmpty());
8589 CHECK(CompileRun("other.js_accessor_p").IsEmpty());
8590 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'js_accessor_p')")
8593 allowed_access = true;
8595 ExpectString("other.js_accessor_p", "getter");
8597 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').get", getter);
8599 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').set", setter);
8601 "Object.getOwnPropertyDescriptor(other, 'js_accessor_p').value");
8603 allowed_access = false;
8605 // Access an element with JS accessor.
8606 CHECK(CompileRun("other[42] = 2").IsEmpty());
8608 CHECK(CompileRun("other[42]").IsEmpty());
8609 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, '42')").IsEmpty());
8611 allowed_access = true;
8613 ExpectString("other[42]", "el_getter");
8614 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').get", el_getter);
8615 ExpectObject("Object.getOwnPropertyDescriptor(other, '42').set", el_setter);
8616 ExpectUndefined("Object.getOwnPropertyDescriptor(other, '42').value");
8618 allowed_access = false;
8620 v8::Handle<Value> value;
8622 // Access accessible property
8623 value = CompileRun("other.accessible_prop = 3");
8624 CHECK(value->IsNumber());
8625 CHECK_EQ(3, value->Int32Value());
8626 CHECK_EQ(3, g_echo_value);
8628 value = CompileRun("other.accessible_prop");
8629 CHECK(value->IsNumber());
8630 CHECK_EQ(3, value->Int32Value());
8633 "Object.getOwnPropertyDescriptor(other, 'accessible_prop').value");
8634 CHECK(value->IsNumber());
8635 CHECK_EQ(3, value->Int32Value());
8637 value = CompileRun("propertyIsEnumerable.call(other, 'accessible_prop')");
8638 CHECK(value->IsTrue());
8640 // Enumeration doesn't enumerate accessors from inaccessible objects in
8641 // the prototype chain even if the accessors are in themselves accessible.
8644 " var obj = { '__proto__': other };"
8646 " for (var p in obj) {"
8647 " if (p == 'accessible_prop' ||"
8648 " p == 'blocked_js_prop' ||"
8649 " p == 'blocked_js_prop') {"
8658 CHECK(value->IsTrue());
8665 TEST(AccessControlES5) {
8666 v8::Isolate* isolate = CcTest::isolate();
8667 v8::HandleScope handle_scope(isolate);
8668 v8::Handle<v8::ObjectTemplate> global_template =
8669 v8::ObjectTemplate::New(isolate);
8671 global_template->SetAccessCheckCallbacks(AccessBlocker, NULL);
8673 // Add accessible accessor.
8674 global_template->SetAccessor(
8675 v8_str("accessible_prop"),
8676 EchoGetter, EchoSetter,
8677 v8::Handle<Value>(),
8678 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8681 // Add an accessor that is not accessible by cross-domain JS code.
8682 global_template->SetAccessor(v8_str("blocked_prop"),
8683 UnreachableGetter, UnreachableSetter,
8684 v8::Handle<Value>(),
8687 // Create an environment
8688 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8691 v8::Handle<v8::Object> global0 = context0->Global();
8693 v8::Local<Context> context1 = Context::New(isolate);
8695 v8::Handle<v8::Object> global1 = context1->Global();
8696 global1->Set(v8_str("other"), global0);
8698 // Regression test for issue 1154.
8699 CHECK(CompileRun("Object.keys(other).length == 0")->BooleanValue());
8700 CHECK(CompileRun("other.blocked_prop").IsEmpty());
8702 // Regression test for issue 1027.
8703 CompileRun("Object.defineProperty(\n"
8704 " other, 'blocked_prop', {configurable: false})");
8705 CHECK(CompileRun("other.blocked_prop").IsEmpty());
8706 CHECK(CompileRun("Object.getOwnPropertyDescriptor(other, 'blocked_prop')")
8709 // Regression test for issue 1171.
8710 ExpectTrue("Object.isExtensible(other)");
8711 CompileRun("Object.preventExtensions(other)");
8712 ExpectTrue("Object.isExtensible(other)");
8714 // Object.seal and Object.freeze.
8715 CompileRun("Object.freeze(other)");
8716 ExpectTrue("Object.isExtensible(other)");
8718 CompileRun("Object.seal(other)");
8719 ExpectTrue("Object.isExtensible(other)");
8721 // Regression test for issue 1250.
8722 // Make sure that we can set the accessible accessors value using normal
8724 CompileRun("other.accessible_prop = 42");
8725 CHECK_EQ(42, g_echo_value);
8727 v8::Handle<Value> value;
8728 CompileRun("Object.defineProperty(other, 'accessible_prop', {value: -1})");
8729 value = CompileRun("other.accessible_prop == 42");
8730 CHECK(value->IsTrue());
8734 static bool AccessAlwaysBlocked(Local<v8::Object> global, Local<Value> name,
8735 v8::AccessType type, Local<Value> data) {
8736 i::PrintF("Access blocked.\n");
8741 THREADED_TEST(AccessControlGetOwnPropertyNames) {
8742 v8::Isolate* isolate = CcTest::isolate();
8743 v8::HandleScope handle_scope(isolate);
8744 v8::Handle<v8::ObjectTemplate> obj_template =
8745 v8::ObjectTemplate::New(isolate);
8747 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
8748 obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8750 // Add an accessor accessible by cross-domain JS code.
8751 obj_template->SetAccessor(
8752 v8_str("accessible_prop"), EchoGetter, EchoSetter, v8::Handle<Value>(),
8753 v8::AccessControl(v8::ALL_CAN_READ | v8::ALL_CAN_WRITE));
8755 // Create an environment
8756 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
8759 v8::Handle<v8::Object> global0 = context0->Global();
8761 v8::HandleScope scope1(CcTest::isolate());
8763 v8::Local<Context> context1 = Context::New(isolate);
8766 v8::Handle<v8::Object> global1 = context1->Global();
8767 global1->Set(v8_str("other"), global0);
8768 global1->Set(v8_str("object"), obj_template->NewInstance());
8770 v8::Handle<Value> value;
8772 // Attempt to get the property names of the other global object and
8773 // of an object that requires access checks. Accessing the other
8774 // global object should be blocked by access checks on the global
8775 // proxy object. Accessing the object that requires access checks
8776 // is blocked by the access checks on the object itself.
8778 "var names = Object.getOwnPropertyNames(other);"
8779 "names.length == 1 && names[0] == 'accessible_prop';");
8780 CHECK(value->BooleanValue());
8783 "var names = Object.getOwnPropertyNames(object);"
8784 "names.length == 1 && names[0] == 'accessible_prop';");
8785 CHECK(value->BooleanValue());
8792 TEST(SuperAccessControl) {
8793 i::FLAG_allow_natives_syntax = true;
8794 v8::Isolate* isolate = CcTest::isolate();
8795 v8::HandleScope handle_scope(isolate);
8796 v8::Handle<v8::ObjectTemplate> obj_template =
8797 v8::ObjectTemplate::New(isolate);
8798 obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8800 env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
8803 v8::TryCatch try_catch(isolate);
8805 "var f = { m() { return super.hasOwnProperty; } }.m;"
8806 "var m = %ToMethod(f, prohibited);"
8808 CHECK(try_catch.HasCaught());
8812 v8::TryCatch try_catch(isolate);
8814 "var f = {m() { return super[42]; } }.m;"
8815 "var m = %ToMethod(f, prohibited);"
8817 CHECK(try_catch.HasCaught());
8821 v8::TryCatch try_catch(isolate);
8823 "var f = {m() { super.hasOwnProperty = function () {}; } }.m;"
8824 "var m = %ToMethod(f, prohibited);"
8826 CHECK(try_catch.HasCaught());
8830 v8::TryCatch try_catch(isolate);
8832 "Object.defineProperty(Object.prototype, 'x', { set : function(){}});"
8836 " super.x = function () {};"
8839 "var m = %ToMethod(f, prohibited);"
8841 CHECK(try_catch.HasCaught());
8846 TEST(Regress470113) {
8847 v8::Isolate* isolate = CcTest::isolate();
8848 v8::HandleScope handle_scope(isolate);
8849 v8::Handle<v8::ObjectTemplate> obj_template =
8850 v8::ObjectTemplate::New(isolate);
8851 obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
8853 env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
8856 v8::TryCatch try_catch(isolate);
8859 "class C extends Object {\n"
8860 " m() { super.powned = 'Powned!'; }\n"
8862 "let c = new C();\n"
8863 "c.m.call(prohibited)");
8865 CHECK(try_catch.HasCaught());
8870 static void ConstTenGetter(Local<String> name,
8871 const v8::PropertyCallbackInfo<v8::Value>& info) {
8872 info.GetReturnValue().Set(v8_num(10));
8876 THREADED_TEST(CrossDomainAccessors) {
8877 v8::Isolate* isolate = CcTest::isolate();
8878 v8::HandleScope handle_scope(isolate);
8880 v8::Handle<v8::FunctionTemplate> func_template =
8881 v8::FunctionTemplate::New(isolate);
8883 v8::Handle<v8::ObjectTemplate> global_template =
8884 func_template->InstanceTemplate();
8886 v8::Handle<v8::ObjectTemplate> proto_template =
8887 func_template->PrototypeTemplate();
8889 // Add an accessor to proto that's accessible by cross-domain JS code.
8890 proto_template->SetAccessor(v8_str("accessible"),
8892 v8::Handle<Value>(),
8895 // Add an accessor that is not accessible by cross-domain JS code.
8896 global_template->SetAccessor(v8_str("unreachable"),
8897 UnreachableGetter, 0,
8898 v8::Handle<Value>(),
8901 v8::Local<Context> context0 = Context::New(isolate, NULL, global_template);
8904 Local<v8::Object> global = context0->Global();
8905 // Add a normal property that shadows 'accessible'
8906 global->Set(v8_str("accessible"), v8_num(11));
8908 // Enter a new context.
8909 v8::HandleScope scope1(CcTest::isolate());
8910 v8::Local<Context> context1 = Context::New(isolate);
8913 v8::Handle<v8::Object> global1 = context1->Global();
8914 global1->Set(v8_str("other"), global);
8916 // Should return 10, instead of 11
8917 v8::Handle<Value> value = v8_compile("other.accessible")->Run();
8918 CHECK(value->IsNumber());
8919 CHECK_EQ(10, value->Int32Value());
8921 value = v8_compile("other.unreachable")->Run();
8922 CHECK(value.IsEmpty());
8929 static int access_count = 0;
8931 static bool AccessCounter(Local<v8::Object> global, Local<Value> name,
8932 v8::AccessType type, Local<Value> data) {
8938 // This one is too easily disturbed by other tests.
8939 TEST(AccessControlIC) {
8942 v8::Isolate* isolate = CcTest::isolate();
8943 v8::HandleScope handle_scope(isolate);
8945 // Create an environment.
8946 v8::Local<Context> context0 = Context::New(isolate);
8949 // Create an object that requires access-check functions to be
8950 // called for cross-domain access.
8951 v8::Handle<v8::ObjectTemplate> object_template =
8952 v8::ObjectTemplate::New(isolate);
8953 object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
8954 Local<v8::Object> object = object_template->NewInstance();
8956 v8::HandleScope scope1(isolate);
8958 // Create another environment.
8959 v8::Local<Context> context1 = Context::New(isolate);
8962 // Make easy access to the object from the other environment.
8963 v8::Handle<v8::Object> global1 = context1->Global();
8964 global1->Set(v8_str("obj"), object);
8966 v8::Handle<Value> value;
8968 // Check that the named access-control function is called every time.
8969 CompileRun("function testProp(obj) {"
8970 " for (var i = 0; i < 10; i++) obj.prop = 1;"
8971 " for (var j = 0; j < 10; j++) obj.prop;"
8974 value = CompileRun("testProp(obj)");
8975 CHECK(value->IsNumber());
8976 CHECK_EQ(1, value->Int32Value());
8977 CHECK_EQ(21, access_count);
8979 // Check that the named access-control function is called every time.
8980 CompileRun("var p = 'prop';"
8981 "function testKeyed(obj) {"
8982 " for (var i = 0; i < 10; i++) obj[p] = 1;"
8983 " for (var j = 0; j < 10; j++) obj[p];"
8986 // Use obj which requires access checks. No inline caching is used
8988 value = CompileRun("testKeyed(obj)");
8989 CHECK(value->IsNumber());
8990 CHECK_EQ(1, value->Int32Value());
8991 CHECK_EQ(42, access_count);
8992 // Force the inline caches into generic state and try again.
8993 CompileRun("testKeyed({ a: 0 })");
8994 CompileRun("testKeyed({ b: 0 })");
8995 value = CompileRun("testKeyed(obj)");
8996 CHECK(value->IsNumber());
8997 CHECK_EQ(1, value->Int32Value());
8998 CHECK_EQ(63, access_count);
9000 // Check that the indexed access-control function is called every time.
9003 CompileRun("function testIndexed(obj) {"
9004 " for (var i = 0; i < 10; i++) obj[0] = 1;"
9005 " for (var j = 0; j < 10; j++) obj[0];"
9008 value = CompileRun("testIndexed(obj)");
9009 CHECK(value->IsNumber());
9010 CHECK_EQ(1, value->Int32Value());
9011 CHECK_EQ(21, access_count);
9012 // Force the inline caches into generic state.
9013 CompileRun("testIndexed(new Array(1))");
9014 // Test that the indexed access check is called.
9015 value = CompileRun("testIndexed(obj)");
9016 CHECK(value->IsNumber());
9017 CHECK_EQ(1, value->Int32Value());
9018 CHECK_EQ(42, access_count);
9021 // Check that the named access check is called when invoking
9022 // functions on an object that requires access checks.
9023 CompileRun("obj.f = function() {}");
9024 CompileRun("function testCallNormal(obj) {"
9025 " for (var i = 0; i < 10; i++) obj.f();"
9027 CompileRun("testCallNormal(obj)");
9028 printf("%i\n", access_count);
9029 CHECK_EQ(11, access_count);
9031 // Force obj into slow case.
9032 value = CompileRun("delete obj.prop");
9033 CHECK(value->BooleanValue());
9034 // Force inline caches into dictionary probing mode.
9035 CompileRun("var o = { x: 0 }; delete o.x; testProp(o);");
9036 // Test that the named access check is called.
9037 value = CompileRun("testProp(obj);");
9038 CHECK(value->IsNumber());
9039 CHECK_EQ(1, value->Int32Value());
9040 CHECK_EQ(33, access_count);
9042 // Force the call inline cache into dictionary probing mode.
9043 CompileRun("o.f = function() {}; testCallNormal(o)");
9044 // Test that the named access check is still called for each
9045 // invocation of the function.
9046 value = CompileRun("testCallNormal(obj)");
9047 CHECK_EQ(43, access_count);
9054 THREADED_TEST(Version) { v8::V8::GetVersion(); }
9057 static void InstanceFunctionCallback(
9058 const v8::FunctionCallbackInfo<v8::Value>& args) {
9059 ApiTestFuzzer::Fuzz();
9060 args.GetReturnValue().Set(v8_num(12));
9064 THREADED_TEST(InstanceProperties) {
9065 LocalContext context;
9066 v8::Isolate* isolate = context->GetIsolate();
9067 v8::HandleScope handle_scope(isolate);
9069 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9070 Local<ObjectTemplate> instance = t->InstanceTemplate();
9072 instance->Set(v8_str("x"), v8_num(42));
9073 instance->Set(v8_str("f"),
9074 v8::FunctionTemplate::New(isolate, InstanceFunctionCallback));
9076 Local<Value> o = t->GetFunction()->NewInstance();
9078 context->Global()->Set(v8_str("i"), o);
9079 Local<Value> value = CompileRun("i.x");
9080 CHECK_EQ(42, value->Int32Value());
9082 value = CompileRun("i.f()");
9083 CHECK_EQ(12, value->Int32Value());
9087 static void GlobalObjectInstancePropertiesGet(
9088 Local<Name> key, const v8::PropertyCallbackInfo<v8::Value>&) {
9089 ApiTestFuzzer::Fuzz();
9093 THREADED_TEST(GlobalObjectInstanceProperties) {
9094 v8::Isolate* isolate = CcTest::isolate();
9095 v8::HandleScope handle_scope(isolate);
9097 Local<Value> global_object;
9099 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9100 t->InstanceTemplate()->SetHandler(
9101 v8::NamedPropertyHandlerConfiguration(GlobalObjectInstancePropertiesGet));
9102 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9103 instance_template->Set(v8_str("x"), v8_num(42));
9104 instance_template->Set(v8_str("f"),
9105 v8::FunctionTemplate::New(isolate,
9106 InstanceFunctionCallback));
9108 // The script to check how Crankshaft compiles missing global function
9109 // invocations. function g is not defined and should throw on call.
9110 const char* script =
9111 "function wrapper(call) {"
9112 " var x = 0, y = 1;"
9113 " for (var i = 0; i < 1000; i++) {"
9119 "for (var i = 0; i < 17; i++) wrapper(false);"
9121 "try { wrapper(true); } catch (e) { thrown = 1; };"
9125 LocalContext env(NULL, instance_template);
9126 // Hold on to the global object so it can be used again in another
9127 // environment initialization.
9128 global_object = env->Global();
9130 Local<Value> value = CompileRun("x");
9131 CHECK_EQ(42, value->Int32Value());
9132 value = CompileRun("f()");
9133 CHECK_EQ(12, value->Int32Value());
9134 value = CompileRun(script);
9135 CHECK_EQ(1, value->Int32Value());
9139 // Create new environment reusing the global object.
9140 LocalContext env(NULL, instance_template, global_object);
9141 Local<Value> value = CompileRun("x");
9142 CHECK_EQ(42, value->Int32Value());
9143 value = CompileRun("f()");
9144 CHECK_EQ(12, value->Int32Value());
9145 value = CompileRun(script);
9146 CHECK_EQ(1, value->Int32Value());
9151 THREADED_TEST(CallKnownGlobalReceiver) {
9152 v8::Isolate* isolate = CcTest::isolate();
9153 v8::HandleScope handle_scope(isolate);
9155 Local<Value> global_object;
9157 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9158 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
9160 // The script to check that we leave global object not
9161 // global object proxy on stack when we deoptimize from inside
9162 // arguments evaluation.
9163 // To provoke error we need to both force deoptimization
9164 // from arguments evaluation and to force CallIC to take
9165 // CallIC_Miss code path that can't cope with global proxy.
9166 const char* script =
9167 "function bar(x, y) { try { } finally { } }"
9168 "function baz(x) { try { } finally { } }"
9169 "function bom(x) { try { } finally { } }"
9170 "function foo(x) { bar([x], bom(2)); }"
9171 "for (var i = 0; i < 10000; i++) foo(1);"
9176 LocalContext env(NULL, instance_template);
9177 // Hold on to the global object so it can be used again in another
9178 // environment initialization.
9179 global_object = env->Global();
9180 foo = CompileRun(script);
9184 // Create new environment reusing the global object.
9185 LocalContext env(NULL, instance_template, global_object);
9186 env->Global()->Set(v8_str("foo"), foo);
9187 CompileRun("foo()");
9192 static void ShadowFunctionCallback(
9193 const v8::FunctionCallbackInfo<v8::Value>& args) {
9194 ApiTestFuzzer::Fuzz();
9195 args.GetReturnValue().Set(v8_num(42));
9199 static int shadow_y;
9200 static int shadow_y_setter_call_count;
9201 static int shadow_y_getter_call_count;
9204 static void ShadowYSetter(Local<String>,
9206 const v8::PropertyCallbackInfo<void>&) {
9207 shadow_y_setter_call_count++;
9212 static void ShadowYGetter(Local<String> name,
9213 const v8::PropertyCallbackInfo<v8::Value>& info) {
9214 ApiTestFuzzer::Fuzz();
9215 shadow_y_getter_call_count++;
9216 info.GetReturnValue().Set(v8_num(shadow_y));
9220 static void ShadowIndexedGet(uint32_t index,
9221 const v8::PropertyCallbackInfo<v8::Value>&) {
9225 static void ShadowNamedGet(Local<Name> key,
9226 const v8::PropertyCallbackInfo<v8::Value>&) {}
9229 THREADED_TEST(ShadowObject) {
9230 shadow_y = shadow_y_setter_call_count = shadow_y_getter_call_count = 0;
9231 v8::Isolate* isolate = CcTest::isolate();
9232 v8::HandleScope handle_scope(isolate);
9234 Local<ObjectTemplate> global_template = v8::ObjectTemplate::New(isolate);
9235 LocalContext context(NULL, global_template);
9237 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9238 t->InstanceTemplate()->SetHandler(
9239 v8::NamedPropertyHandlerConfiguration(ShadowNamedGet));
9240 t->InstanceTemplate()->SetHandler(
9241 v8::IndexedPropertyHandlerConfiguration(ShadowIndexedGet));
9242 Local<ObjectTemplate> proto = t->PrototypeTemplate();
9243 Local<ObjectTemplate> instance = t->InstanceTemplate();
9245 proto->Set(v8_str("f"),
9246 v8::FunctionTemplate::New(isolate,
9247 ShadowFunctionCallback,
9249 proto->Set(v8_str("x"), v8_num(12));
9251 instance->SetAccessor(v8_str("y"), ShadowYGetter, ShadowYSetter);
9253 Local<Value> o = t->GetFunction()->NewInstance();
9254 context->Global()->Set(v8_str("__proto__"), o);
9256 Local<Value> value =
9257 CompileRun("this.propertyIsEnumerable(0)");
9258 CHECK(value->IsBoolean());
9259 CHECK(!value->BooleanValue());
9261 value = CompileRun("x");
9262 CHECK_EQ(12, value->Int32Value());
9264 value = CompileRun("f()");
9265 CHECK_EQ(42, value->Int32Value());
9267 CompileRun("y = 43");
9268 CHECK_EQ(1, shadow_y_setter_call_count);
9269 value = CompileRun("y");
9270 CHECK_EQ(1, shadow_y_getter_call_count);
9271 CHECK_EQ(42, value->Int32Value());
9275 THREADED_TEST(HiddenPrototype) {
9276 LocalContext context;
9277 v8::Isolate* isolate = context->GetIsolate();
9278 v8::HandleScope handle_scope(isolate);
9280 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9281 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9282 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9283 t1->SetHiddenPrototype(true);
9284 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9285 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9286 t2->SetHiddenPrototype(true);
9287 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9288 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9289 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9291 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9292 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9293 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9294 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9296 // Setting the prototype on an object skips hidden prototypes.
9297 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9298 o0->Set(v8_str("__proto__"), o1);
9299 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9300 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9301 o0->Set(v8_str("__proto__"), o2);
9302 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9303 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9304 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9305 o0->Set(v8_str("__proto__"), o3);
9306 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9307 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9308 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9309 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9311 // Getting the prototype of o0 should get the first visible one
9312 // which is o3. Therefore, z should not be defined on the prototype
9314 Local<Value> proto = o0->Get(v8_str("__proto__"));
9315 CHECK(proto->IsObject());
9316 CHECK(proto.As<v8::Object>()->Get(v8_str("z"))->IsUndefined());
9320 THREADED_TEST(HiddenPrototypeSet) {
9321 LocalContext context;
9322 v8::Isolate* isolate = context->GetIsolate();
9323 v8::HandleScope handle_scope(isolate);
9325 Local<v8::FunctionTemplate> ot = v8::FunctionTemplate::New(isolate);
9326 Local<v8::FunctionTemplate> ht = v8::FunctionTemplate::New(isolate);
9327 ht->SetHiddenPrototype(true);
9328 Local<v8::FunctionTemplate> pt = v8::FunctionTemplate::New(isolate);
9329 ht->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9331 Local<v8::Object> o = ot->GetFunction()->NewInstance();
9332 Local<v8::Object> h = ht->GetFunction()->NewInstance();
9333 Local<v8::Object> p = pt->GetFunction()->NewInstance();
9334 o->Set(v8_str("__proto__"), h);
9335 h->Set(v8_str("__proto__"), p);
9337 // Setting a property that exists on the hidden prototype goes there.
9338 o->Set(v8_str("x"), v8_num(7));
9339 CHECK_EQ(7, o->Get(v8_str("x"))->Int32Value());
9340 CHECK_EQ(7, h->Get(v8_str("x"))->Int32Value());
9341 CHECK(p->Get(v8_str("x"))->IsUndefined());
9343 // Setting a new property should not be forwarded to the hidden prototype.
9344 o->Set(v8_str("y"), v8_num(6));
9345 CHECK_EQ(6, o->Get(v8_str("y"))->Int32Value());
9346 CHECK(h->Get(v8_str("y"))->IsUndefined());
9347 CHECK(p->Get(v8_str("y"))->IsUndefined());
9349 // Setting a property that only exists on a prototype of the hidden prototype
9350 // is treated normally again.
9351 p->Set(v8_str("z"), v8_num(8));
9352 CHECK_EQ(8, o->Get(v8_str("z"))->Int32Value());
9353 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9354 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9355 o->Set(v8_str("z"), v8_num(9));
9356 CHECK_EQ(9, o->Get(v8_str("z"))->Int32Value());
9357 CHECK_EQ(8, h->Get(v8_str("z"))->Int32Value());
9358 CHECK_EQ(8, p->Get(v8_str("z"))->Int32Value());
9362 // Regression test for issue 2457.
9363 THREADED_TEST(HiddenPrototypeIdentityHash) {
9364 LocalContext context;
9365 v8::HandleScope handle_scope(context->GetIsolate());
9367 Handle<FunctionTemplate> t = FunctionTemplate::New(context->GetIsolate());
9368 t->SetHiddenPrototype(true);
9369 t->InstanceTemplate()->Set(v8_str("foo"), v8_num(75));
9370 Handle<Object> p = t->GetFunction()->NewInstance();
9371 Handle<Object> o = Object::New(context->GetIsolate());
9374 int hash = o->GetIdentityHash();
9376 o->Set(v8_str("foo"), v8_num(42));
9377 DCHECK_EQ(hash, o->GetIdentityHash());
9381 THREADED_TEST(SetPrototype) {
9382 LocalContext context;
9383 v8::Isolate* isolate = context->GetIsolate();
9384 v8::HandleScope handle_scope(isolate);
9386 Local<v8::FunctionTemplate> t0 = v8::FunctionTemplate::New(isolate);
9387 t0->InstanceTemplate()->Set(v8_str("x"), v8_num(0));
9388 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9389 t1->SetHiddenPrototype(true);
9390 t1->InstanceTemplate()->Set(v8_str("y"), v8_num(1));
9391 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9392 t2->SetHiddenPrototype(true);
9393 t2->InstanceTemplate()->Set(v8_str("z"), v8_num(2));
9394 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9395 t3->InstanceTemplate()->Set(v8_str("u"), v8_num(3));
9397 Local<v8::Object> o0 = t0->GetFunction()->NewInstance();
9398 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9399 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9400 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9402 // Setting the prototype on an object does not skip hidden prototypes.
9403 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9404 CHECK(o0->SetPrototype(o1));
9405 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9406 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9407 CHECK(o1->SetPrototype(o2));
9408 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9409 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9410 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9411 CHECK(o2->SetPrototype(o3));
9412 CHECK_EQ(0, o0->Get(v8_str("x"))->Int32Value());
9413 CHECK_EQ(1, o0->Get(v8_str("y"))->Int32Value());
9414 CHECK_EQ(2, o0->Get(v8_str("z"))->Int32Value());
9415 CHECK_EQ(3, o0->Get(v8_str("u"))->Int32Value());
9417 // Getting the prototype of o0 should get the first visible one
9418 // which is o3. Therefore, z should not be defined on the prototype
9420 Local<Value> proto = o0->Get(v8_str("__proto__"));
9421 CHECK(proto->IsObject());
9422 CHECK(proto.As<v8::Object>()->Equals(o3));
9424 // However, Object::GetPrototype ignores hidden prototype.
9425 Local<Value> proto0 = o0->GetPrototype();
9426 CHECK(proto0->IsObject());
9427 CHECK(proto0.As<v8::Object>()->Equals(o1));
9429 Local<Value> proto1 = o1->GetPrototype();
9430 CHECK(proto1->IsObject());
9431 CHECK(proto1.As<v8::Object>()->Equals(o2));
9433 Local<Value> proto2 = o2->GetPrototype();
9434 CHECK(proto2->IsObject());
9435 CHECK(proto2.As<v8::Object>()->Equals(o3));
9439 // Getting property names of an object with a prototype chain that
9440 // triggers dictionary elements in GetOwnPropertyNames() shouldn't
9441 // crash the runtime.
9442 THREADED_TEST(Regress91517) {
9443 i::FLAG_allow_natives_syntax = true;
9444 LocalContext context;
9445 v8::Isolate* isolate = context->GetIsolate();
9446 v8::HandleScope handle_scope(isolate);
9448 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9449 t1->SetHiddenPrototype(true);
9450 t1->InstanceTemplate()->Set(v8_str("foo"), v8_num(1));
9451 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9452 t2->SetHiddenPrototype(true);
9453 t2->InstanceTemplate()->Set(v8_str("fuz1"), v8_num(2));
9454 t2->InstanceTemplate()->Set(v8_str("objects"), v8::Object::New(isolate));
9455 t2->InstanceTemplate()->Set(v8_str("fuz2"), v8_num(2));
9456 Local<v8::FunctionTemplate> t3 = v8::FunctionTemplate::New(isolate);
9457 t3->SetHiddenPrototype(true);
9458 t3->InstanceTemplate()->Set(v8_str("boo"), v8_num(3));
9459 Local<v8::FunctionTemplate> t4 = v8::FunctionTemplate::New(isolate);
9460 t4->InstanceTemplate()->Set(v8_str("baz"), v8_num(4));
9462 // Force dictionary-based properties.
9463 i::ScopedVector<char> name_buf(1024);
9464 for (int i = 1; i <= 1000; i++) {
9465 i::SNPrintF(name_buf, "sdf%d", i);
9466 t2->InstanceTemplate()->Set(v8_str(name_buf.start()), v8_num(2));
9469 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9470 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9471 Local<v8::Object> o3 = t3->GetFunction()->NewInstance();
9472 Local<v8::Object> o4 = t4->GetFunction()->NewInstance();
9474 // Create prototype chain of hidden prototypes.
9475 CHECK(o4->SetPrototype(o3));
9476 CHECK(o3->SetPrototype(o2));
9477 CHECK(o2->SetPrototype(o1));
9479 // Call the runtime version of GetOwnPropertyNames() on the natively
9480 // created object through JavaScript.
9481 context->Global()->Set(v8_str("obj"), o4);
9482 // PROPERTY_ATTRIBUTES_NONE = 0
9483 CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9485 ExpectInt32("names.length", 1006);
9486 ExpectTrue("names.indexOf(\"baz\") >= 0");
9487 ExpectTrue("names.indexOf(\"boo\") >= 0");
9488 ExpectTrue("names.indexOf(\"foo\") >= 0");
9489 ExpectTrue("names.indexOf(\"fuz1\") >= 0");
9490 ExpectTrue("names.indexOf(\"fuz2\") >= 0");
9491 ExpectFalse("names[1005] == undefined");
9495 // Getting property names of an object with a hidden and inherited
9496 // prototype should not duplicate the accessor properties inherited.
9497 THREADED_TEST(Regress269562) {
9498 i::FLAG_allow_natives_syntax = true;
9499 LocalContext context;
9500 v8::HandleScope handle_scope(context->GetIsolate());
9502 Local<v8::FunctionTemplate> t1 =
9503 v8::FunctionTemplate::New(context->GetIsolate());
9504 t1->SetHiddenPrototype(true);
9506 Local<v8::ObjectTemplate> i1 = t1->InstanceTemplate();
9507 i1->SetAccessor(v8_str("foo"),
9508 SimpleAccessorGetter, SimpleAccessorSetter);
9509 i1->SetAccessor(v8_str("bar"),
9510 SimpleAccessorGetter, SimpleAccessorSetter);
9511 i1->SetAccessor(v8_str("baz"),
9512 SimpleAccessorGetter, SimpleAccessorSetter);
9513 i1->Set(v8_str("n1"), v8_num(1));
9514 i1->Set(v8_str("n2"), v8_num(2));
9516 Local<v8::Object> o1 = t1->GetFunction()->NewInstance();
9517 Local<v8::FunctionTemplate> t2 =
9518 v8::FunctionTemplate::New(context->GetIsolate());
9519 t2->SetHiddenPrototype(true);
9521 // Inherit from t1 and mark prototype as hidden.
9523 t2->InstanceTemplate()->Set(v8_str("mine"), v8_num(4));
9525 Local<v8::Object> o2 = t2->GetFunction()->NewInstance();
9526 CHECK(o2->SetPrototype(o1));
9528 v8::Local<v8::Symbol> sym =
9529 v8::Symbol::New(context->GetIsolate(), v8_str("s1"));
9530 o1->Set(sym, v8_num(3));
9532 v8_str("h1"), v8::Integer::New(context->GetIsolate(), 2013));
9534 // Call the runtime version of GetOwnPropertyNames() on
9535 // the natively created object through JavaScript.
9536 context->Global()->Set(v8_str("obj"), o2);
9537 context->Global()->Set(v8_str("sym"), sym);
9538 // PROPERTY_ATTRIBUTES_NONE = 0
9539 CompileRun("var names = %GetOwnPropertyNames(obj, 0);");
9541 ExpectInt32("names.length", 7);
9542 ExpectTrue("names.indexOf(\"foo\") >= 0");
9543 ExpectTrue("names.indexOf(\"bar\") >= 0");
9544 ExpectTrue("names.indexOf(\"baz\") >= 0");
9545 ExpectTrue("names.indexOf(\"n1\") >= 0");
9546 ExpectTrue("names.indexOf(\"n2\") >= 0");
9547 ExpectTrue("names.indexOf(sym) >= 0");
9548 ExpectTrue("names.indexOf(\"mine\") >= 0");
9552 THREADED_TEST(FunctionReadOnlyPrototype) {
9553 LocalContext context;
9554 v8::Isolate* isolate = context->GetIsolate();
9555 v8::HandleScope handle_scope(isolate);
9557 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9558 t1->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9559 t1->ReadOnlyPrototype();
9560 context->Global()->Set(v8_str("func1"), t1->GetFunction());
9561 // Configured value of ReadOnly flag.
9564 " descriptor = Object.getOwnPropertyDescriptor(func1, 'prototype');"
9565 " return (descriptor['writable'] == false);"
9566 "})()")->BooleanValue());
9567 CHECK_EQ(42, CompileRun("func1.prototype.x")->Int32Value());
9569 CompileRun("func1.prototype = {}; func1.prototype.x")->Int32Value());
9571 Local<v8::FunctionTemplate> t2 = v8::FunctionTemplate::New(isolate);
9572 t2->PrototypeTemplate()->Set(v8_str("x"), v8::Integer::New(isolate, 42));
9573 context->Global()->Set(v8_str("func2"), t2->GetFunction());
9574 // Default value of ReadOnly flag.
9577 " descriptor = Object.getOwnPropertyDescriptor(func2, 'prototype');"
9578 " return (descriptor['writable'] == true);"
9579 "})()")->BooleanValue());
9580 CHECK_EQ(42, CompileRun("func2.prototype.x")->Int32Value());
9584 THREADED_TEST(SetPrototypeThrows) {
9585 LocalContext context;
9586 v8::Isolate* isolate = context->GetIsolate();
9587 v8::HandleScope handle_scope(isolate);
9589 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
9591 Local<v8::Object> o0 = t->GetFunction()->NewInstance();
9592 Local<v8::Object> o1 = t->GetFunction()->NewInstance();
9594 CHECK(o0->SetPrototype(o1));
9595 // If setting the prototype leads to the cycle, SetPrototype should
9596 // return false and keep VM in sane state.
9597 v8::TryCatch try_catch(isolate);
9598 CHECK(!o1->SetPrototype(o0));
9599 CHECK(!try_catch.HasCaught());
9600 DCHECK(!CcTest::i_isolate()->has_pending_exception());
9602 CHECK_EQ(42, CompileRun("function f() { return 42; }; f()")->Int32Value());
9606 THREADED_TEST(FunctionRemovePrototype) {
9607 LocalContext context;
9608 v8::Isolate* isolate = context->GetIsolate();
9609 v8::HandleScope handle_scope(isolate);
9611 Local<v8::FunctionTemplate> t1 = v8::FunctionTemplate::New(isolate);
9612 t1->RemovePrototype();
9613 Local<v8::Function> fun = t1->GetFunction();
9614 context->Global()->Set(v8_str("fun"), fun);
9615 CHECK(!CompileRun("'prototype' in fun")->BooleanValue());
9617 v8::TryCatch try_catch(isolate);
9618 CompileRun("new fun()");
9619 CHECK(try_catch.HasCaught());
9623 CHECK(try_catch.HasCaught());
9627 THREADED_TEST(GetterSetterExceptions) {
9628 LocalContext context;
9629 v8::Isolate* isolate = context->GetIsolate();
9630 v8::HandleScope handle_scope(isolate);
9632 "function Foo() { };"
9633 "function Throw() { throw 5; };"
9635 "x.__defineSetter__('set', Throw);"
9636 "x.__defineGetter__('get', Throw);");
9637 Local<v8::Object> x =
9638 Local<v8::Object>::Cast(context->Global()->Get(v8_str("x")));
9639 v8::TryCatch try_catch(isolate);
9640 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9641 x->Get(v8_str("get"));
9642 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9643 x->Get(v8_str("get"));
9644 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9645 x->Get(v8_str("get"));
9646 x->Set(v8_str("set"), v8::Integer::New(isolate, 8));
9647 x->Get(v8_str("get"));
9651 THREADED_TEST(Constructor) {
9652 LocalContext context;
9653 v8::Isolate* isolate = context->GetIsolate();
9654 v8::HandleScope handle_scope(isolate);
9655 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9656 templ->SetClassName(v8_str("Fun"));
9657 Local<Function> cons = templ->GetFunction();
9658 context->Global()->Set(v8_str("Fun"), cons);
9659 Local<v8::Object> inst = cons->NewInstance();
9660 i::Handle<i::JSObject> obj(v8::Utils::OpenHandle(*inst));
9661 CHECK(obj->IsJSObject());
9662 Local<Value> value = CompileRun("(new Fun()).constructor === Fun");
9663 CHECK(value->BooleanValue());
9667 static void ConstructorCallback(
9668 const v8::FunctionCallbackInfo<v8::Value>& args) {
9669 ApiTestFuzzer::Fuzz();
9672 if (args.IsConstructCall()) {
9673 Local<Object> Holder = args.Holder();
9674 This = Object::New(args.GetIsolate());
9675 Local<Value> proto = Holder->GetPrototype();
9676 if (proto->IsObject()) {
9677 This->SetPrototype(proto);
9683 This->Set(v8_str("a"), args[0]);
9684 args.GetReturnValue().Set(This);
9688 static void FakeConstructorCallback(
9689 const v8::FunctionCallbackInfo<v8::Value>& args) {
9690 ApiTestFuzzer::Fuzz();
9691 args.GetReturnValue().Set(args[0]);
9695 THREADED_TEST(ConstructorForObject) {
9696 LocalContext context;
9697 v8::Isolate* isolate = context->GetIsolate();
9698 v8::HandleScope handle_scope(isolate);
9701 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9702 instance_template->SetCallAsFunctionHandler(ConstructorCallback);
9703 Local<Object> instance = instance_template->NewInstance();
9704 context->Global()->Set(v8_str("obj"), instance);
9705 v8::TryCatch try_catch(isolate);
9707 CHECK(!try_catch.HasCaught());
9709 // Call the Object's constructor with a 32-bit signed integer.
9710 value = CompileRun("(function() { var o = new obj(28); return o.a; })()");
9711 CHECK(!try_catch.HasCaught());
9712 CHECK(value->IsInt32());
9713 CHECK_EQ(28, value->Int32Value());
9715 Local<Value> args1[] = {v8_num(28)};
9716 Local<Value> value_obj1 = instance->CallAsConstructor(1, args1);
9717 CHECK(value_obj1->IsObject());
9718 Local<Object> object1 = Local<Object>::Cast(value_obj1);
9719 value = object1->Get(v8_str("a"));
9720 CHECK(value->IsInt32());
9721 CHECK(!try_catch.HasCaught());
9722 CHECK_EQ(28, value->Int32Value());
9724 // Call the Object's constructor with a String.
9726 CompileRun("(function() { var o = new obj('tipli'); return o.a; })()");
9727 CHECK(!try_catch.HasCaught());
9728 CHECK(value->IsString());
9729 String::Utf8Value string_value1(value->ToString(isolate));
9730 CHECK_EQ(0, strcmp("tipli", *string_value1));
9732 Local<Value> args2[] = {v8_str("tipli")};
9733 Local<Value> value_obj2 = instance->CallAsConstructor(1, args2);
9734 CHECK(value_obj2->IsObject());
9735 Local<Object> object2 = Local<Object>::Cast(value_obj2);
9736 value = object2->Get(v8_str("a"));
9737 CHECK(!try_catch.HasCaught());
9738 CHECK(value->IsString());
9739 String::Utf8Value string_value2(value->ToString(isolate));
9740 CHECK_EQ(0, strcmp("tipli", *string_value2));
9742 // Call the Object's constructor with a Boolean.
9743 value = CompileRun("(function() { var o = new obj(true); return o.a; })()");
9744 CHECK(!try_catch.HasCaught());
9745 CHECK(value->IsBoolean());
9746 CHECK_EQ(true, value->BooleanValue());
9748 Handle<Value> args3[] = {v8::True(isolate)};
9749 Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
9750 CHECK(value_obj3->IsObject());
9751 Local<Object> object3 = Local<Object>::Cast(value_obj3);
9752 value = object3->Get(v8_str("a"));
9753 CHECK(!try_catch.HasCaught());
9754 CHECK(value->IsBoolean());
9755 CHECK_EQ(true, value->BooleanValue());
9757 // Call the Object's constructor with undefined.
9758 Handle<Value> args4[] = {v8::Undefined(isolate)};
9759 Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
9760 CHECK(value_obj4->IsObject());
9761 Local<Object> object4 = Local<Object>::Cast(value_obj4);
9762 value = object4->Get(v8_str("a"));
9763 CHECK(!try_catch.HasCaught());
9764 CHECK(value->IsUndefined());
9766 // Call the Object's constructor with null.
9767 Handle<Value> args5[] = {v8::Null(isolate)};
9768 Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
9769 CHECK(value_obj5->IsObject());
9770 Local<Object> object5 = Local<Object>::Cast(value_obj5);
9771 value = object5->Get(v8_str("a"));
9772 CHECK(!try_catch.HasCaught());
9773 CHECK(value->IsNull());
9776 // Check exception handling when there is no constructor set for the Object.
9778 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9779 Local<Object> instance = instance_template->NewInstance();
9780 context->Global()->Set(v8_str("obj2"), instance);
9781 v8::TryCatch try_catch(isolate);
9783 CHECK(!try_catch.HasCaught());
9785 value = CompileRun("new obj2(28)");
9786 CHECK(try_catch.HasCaught());
9787 String::Utf8Value exception_value1(try_catch.Exception());
9788 CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
9791 Local<Value> args[] = {v8_num(29)};
9792 value = instance->CallAsConstructor(1, args);
9793 CHECK(try_catch.HasCaught());
9794 String::Utf8Value exception_value2(try_catch.Exception());
9796 0, strcmp("TypeError: #<Object> is not a function", *exception_value2));
9800 // Check the case when constructor throws exception.
9802 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9803 instance_template->SetCallAsFunctionHandler(ThrowValue);
9804 Local<Object> instance = instance_template->NewInstance();
9805 context->Global()->Set(v8_str("obj3"), instance);
9806 v8::TryCatch try_catch(isolate);
9808 CHECK(!try_catch.HasCaught());
9810 value = CompileRun("new obj3(22)");
9811 CHECK(try_catch.HasCaught());
9812 String::Utf8Value exception_value1(try_catch.Exception());
9813 CHECK_EQ(0, strcmp("22", *exception_value1));
9816 Local<Value> args[] = {v8_num(23)};
9817 value = instance->CallAsConstructor(1, args);
9818 CHECK(try_catch.HasCaught());
9819 String::Utf8Value exception_value2(try_catch.Exception());
9820 CHECK_EQ(0, strcmp("23", *exception_value2));
9824 // Check whether constructor returns with an object or non-object.
9826 Local<FunctionTemplate> function_template =
9827 FunctionTemplate::New(isolate, FakeConstructorCallback);
9828 Local<Function> function = function_template->GetFunction();
9829 Local<Object> instance1 = function;
9830 context->Global()->Set(v8_str("obj4"), instance1);
9831 v8::TryCatch try_catch(isolate);
9833 CHECK(!try_catch.HasCaught());
9835 CHECK(instance1->IsObject());
9836 CHECK(instance1->IsFunction());
9838 value = CompileRun("new obj4(28)");
9839 CHECK(!try_catch.HasCaught());
9840 CHECK(value->IsObject());
9842 Local<Value> args1[] = {v8_num(28)};
9843 value = instance1->CallAsConstructor(1, args1);
9844 CHECK(!try_catch.HasCaught());
9845 CHECK(value->IsObject());
9847 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
9848 instance_template->SetCallAsFunctionHandler(FakeConstructorCallback);
9849 Local<Object> instance2 = instance_template->NewInstance();
9850 context->Global()->Set(v8_str("obj5"), instance2);
9851 CHECK(!try_catch.HasCaught());
9853 CHECK(instance2->IsObject());
9854 CHECK(!instance2->IsFunction());
9856 value = CompileRun("new obj5(28)");
9857 CHECK(!try_catch.HasCaught());
9858 CHECK(!value->IsObject());
9860 Local<Value> args2[] = {v8_num(28)};
9861 value = instance2->CallAsConstructor(1, args2);
9862 CHECK(!try_catch.HasCaught());
9863 CHECK(!value->IsObject());
9868 THREADED_TEST(FunctionDescriptorException) {
9869 LocalContext context;
9870 v8::Isolate* isolate = context->GetIsolate();
9871 v8::HandleScope handle_scope(isolate);
9872 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
9873 templ->SetClassName(v8_str("Fun"));
9874 Local<Function> cons = templ->GetFunction();
9875 context->Global()->Set(v8_str("Fun"), cons);
9876 Local<Value> value = CompileRun(
9879 " (new Fun()).blah()"
9881 " var str = String(e);"
9882 // " if (str.indexOf('TypeError') == -1) return 1;"
9883 // " if (str.indexOf('[object Fun]') != -1) return 2;"
9884 // " if (str.indexOf('#<Fun>') == -1) return 3;"
9890 CHECK_EQ(0, value->Int32Value());
9894 THREADED_TEST(EvalAliasedDynamic) {
9895 LocalContext current;
9896 v8::HandleScope scope(current->GetIsolate());
9898 // Tests where aliased eval can only be resolved dynamically.
9899 Local<Script> script = v8_compile(
9902 " with (x) { return eval('foo'); }"
9905 "result1 = f(new Object());"
9906 "result2 = f(this);"
9907 "var x = new Object();"
9908 "x.eval = function(x) { return 1; };"
9911 CHECK_EQ(2, current->Global()->Get(v8_str("result1"))->Int32Value());
9912 CHECK_EQ(0, current->Global()->Get(v8_str("result2"))->Int32Value());
9913 CHECK_EQ(1, current->Global()->Get(v8_str("result3"))->Int32Value());
9915 v8::TryCatch try_catch(current->GetIsolate());
9916 script = v8_compile(
9919 " with (x) { return eval('bar'); }"
9921 "result4 = f(this)");
9923 CHECK(!try_catch.HasCaught());
9924 CHECK_EQ(2, current->Global()->Get(v8_str("result4"))->Int32Value());
9930 THREADED_TEST(CrossEval) {
9931 v8::HandleScope scope(CcTest::isolate());
9933 LocalContext current;
9935 Local<String> token = v8_str("<security token>");
9936 other->SetSecurityToken(token);
9937 current->SetSecurityToken(token);
9939 // Set up reference from current to other.
9940 current->Global()->Set(v8_str("other"), other->Global());
9942 // Check that new variables are introduced in other context.
9943 Local<Script> script = v8_compile("other.eval('var foo = 1234')");
9945 Local<Value> foo = other->Global()->Get(v8_str("foo"));
9946 CHECK_EQ(1234, foo->Int32Value());
9947 CHECK(!current->Global()->Has(v8_str("foo")));
9949 // Check that writing to non-existing properties introduces them in
9950 // the other context.
9951 script = v8_compile("other.eval('na = 1234')");
9953 CHECK_EQ(1234, other->Global()->Get(v8_str("na"))->Int32Value());
9954 CHECK(!current->Global()->Has(v8_str("na")));
9956 // Check that global variables in current context are not visible in other
9958 v8::TryCatch try_catch(CcTest::isolate());
9959 script = v8_compile("var bar = 42; other.eval('bar');");
9960 Local<Value> result = script->Run();
9961 CHECK(try_catch.HasCaught());
9964 // Check that local variables in current context are not visible in other
9966 script = v8_compile(
9969 " return other.eval('baz');"
9971 result = script->Run();
9972 CHECK(try_catch.HasCaught());
9975 // Check that global variables in the other environment are visible
9976 // when evaluting code.
9977 other->Global()->Set(v8_str("bis"), v8_num(1234));
9978 script = v8_compile("other.eval('bis')");
9979 CHECK_EQ(1234, script->Run()->Int32Value());
9980 CHECK(!try_catch.HasCaught());
9982 // Check that the 'this' pointer points to the global object evaluating
9984 other->Global()->Set(v8_str("t"), other->Global());
9985 script = v8_compile("other.eval('this == t')");
9986 result = script->Run();
9987 CHECK(result->IsTrue());
9988 CHECK(!try_catch.HasCaught());
9990 // Check that variables introduced in with-statement are not visible in
9992 script = v8_compile("with({x:2}){other.eval('x')}");
9993 result = script->Run();
9994 CHECK(try_catch.HasCaught());
9997 // Check that you cannot use 'eval.call' with another object than the
9998 // current global object.
9999 script = v8_compile("other.y = 1; eval.call(other, 'y')");
10000 result = script->Run();
10001 CHECK(try_catch.HasCaught());
10005 // Test that calling eval in a context which has been detached from
10006 // its global proxy works.
10007 THREADED_TEST(EvalInDetachedGlobal) {
10008 v8::Isolate* isolate = CcTest::isolate();
10009 v8::HandleScope scope(isolate);
10011 v8::Local<Context> context0 = Context::New(isolate);
10012 v8::Local<Context> context1 = Context::New(isolate);
10014 // Set up function in context0 that uses eval from context0.
10016 v8::Handle<v8::Value> fun = CompileRun(
10020 " return function(s) { return e(s); }"
10024 // Put the function into context1 and call it before and after
10025 // detaching the global. Before detaching, the call succeeds and
10026 // after detaching and exception is thrown.
10028 context1->Global()->Set(v8_str("fun"), fun);
10029 v8::Handle<v8::Value> x_value = CompileRun("fun('x')");
10030 CHECK_EQ(42, x_value->Int32Value());
10031 context0->DetachGlobal();
10032 v8::TryCatch catcher(isolate);
10033 x_value = CompileRun("fun('x')");
10034 CHECK_EQ(42, x_value->Int32Value());
10039 THREADED_TEST(CrossLazyLoad) {
10040 v8::HandleScope scope(CcTest::isolate());
10041 LocalContext other;
10042 LocalContext current;
10044 Local<String> token = v8_str("<security token>");
10045 other->SetSecurityToken(token);
10046 current->SetSecurityToken(token);
10048 // Set up reference from current to other.
10049 current->Global()->Set(v8_str("other"), other->Global());
10051 // Trigger lazy loading in other context.
10052 Local<Script> script = v8_compile("other.eval('new Date(42)')");
10053 Local<Value> value = script->Run();
10054 CHECK_EQ(42.0, value->NumberValue());
10058 static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) {
10059 ApiTestFuzzer::Fuzz();
10060 if (args.IsConstructCall()) {
10061 if (args[0]->IsInt32()) {
10062 args.GetReturnValue().Set(v8_num(-args[0]->Int32Value()));
10067 args.GetReturnValue().Set(args[0]);
10071 static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
10072 args.GetReturnValue().Set(args.This());
10076 // Test that a call handler can be set for objects which will allow
10077 // non-function objects created through the API to be called as
10079 THREADED_TEST(CallAsFunction) {
10080 LocalContext context;
10081 v8::Isolate* isolate = context->GetIsolate();
10082 v8::HandleScope scope(isolate);
10085 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10086 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10087 instance_template->SetCallAsFunctionHandler(call_as_function);
10088 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10089 context->Global()->Set(v8_str("obj"), instance);
10090 v8::TryCatch try_catch(isolate);
10091 Local<Value> value;
10092 CHECK(!try_catch.HasCaught());
10094 value = CompileRun("obj(42)");
10095 CHECK(!try_catch.HasCaught());
10096 CHECK_EQ(42, value->Int32Value());
10098 value = CompileRun("(function(o){return o(49)})(obj)");
10099 CHECK(!try_catch.HasCaught());
10100 CHECK_EQ(49, value->Int32Value());
10102 // test special case of call as function
10103 value = CompileRun("[obj]['0'](45)");
10104 CHECK(!try_catch.HasCaught());
10105 CHECK_EQ(45, value->Int32Value());
10107 value = CompileRun(
10108 "obj.call = Function.prototype.call;"
10109 "obj.call(null, 87)");
10110 CHECK(!try_catch.HasCaught());
10111 CHECK_EQ(87, value->Int32Value());
10113 // Regression tests for bug #1116356: Calling call through call/apply
10114 // must work for non-function receivers.
10115 const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])";
10116 value = CompileRun(apply_99);
10117 CHECK(!try_catch.HasCaught());
10118 CHECK_EQ(99, value->Int32Value());
10120 const char* call_17 = "Function.prototype.call.call(obj, this, 17)";
10121 value = CompileRun(call_17);
10122 CHECK(!try_catch.HasCaught());
10123 CHECK_EQ(17, value->Int32Value());
10125 // Check that the call-as-function handler can be called through
10127 value = CompileRun("new obj(43)");
10128 CHECK(!try_catch.HasCaught());
10129 CHECK_EQ(-43, value->Int32Value());
10131 // Check that the call-as-function handler can be called through
10133 v8::Handle<Value> args[] = {v8_num(28)};
10134 value = instance->CallAsFunction(instance, 1, args);
10135 CHECK(!try_catch.HasCaught());
10136 CHECK_EQ(28, value->Int32Value());
10140 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10141 Local<ObjectTemplate> instance_template(t->InstanceTemplate());
10142 USE(instance_template);
10143 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10144 context->Global()->Set(v8_str("obj2"), instance);
10145 v8::TryCatch try_catch(isolate);
10146 Local<Value> value;
10147 CHECK(!try_catch.HasCaught());
10149 // Call an object without call-as-function handler through the JS
10150 value = CompileRun("obj2(28)");
10151 CHECK(value.IsEmpty());
10152 CHECK(try_catch.HasCaught());
10153 String::Utf8Value exception_value1(try_catch.Exception());
10154 // TODO(verwaest): Better message
10155 CHECK_EQ(0, strcmp("TypeError: obj2 is not a function", *exception_value1));
10158 // Call an object without call-as-function handler through the API
10159 value = CompileRun("obj2(28)");
10160 v8::Handle<Value> args[] = {v8_num(28)};
10161 value = instance->CallAsFunction(instance, 1, args);
10162 CHECK(value.IsEmpty());
10163 CHECK(try_catch.HasCaught());
10164 String::Utf8Value exception_value2(try_catch.Exception());
10165 CHECK_EQ(0, strcmp("TypeError: [object Object] is not a function",
10166 *exception_value2));
10171 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10172 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10173 instance_template->SetCallAsFunctionHandler(ThrowValue);
10174 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10175 context->Global()->Set(v8_str("obj3"), instance);
10176 v8::TryCatch try_catch(isolate);
10177 Local<Value> value;
10178 CHECK(!try_catch.HasCaught());
10180 // Catch the exception which is thrown by call-as-function handler
10181 value = CompileRun("obj3(22)");
10182 CHECK(try_catch.HasCaught());
10183 String::Utf8Value exception_value1(try_catch.Exception());
10184 CHECK_EQ(0, strcmp("22", *exception_value1));
10187 v8::Handle<Value> args[] = {v8_num(23)};
10188 value = instance->CallAsFunction(instance, 1, args);
10189 CHECK(try_catch.HasCaught());
10190 String::Utf8Value exception_value2(try_catch.Exception());
10191 CHECK_EQ(0, strcmp("23", *exception_value2));
10196 Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate);
10197 Local<ObjectTemplate> instance_template = t->InstanceTemplate();
10198 instance_template->SetCallAsFunctionHandler(ReturnThis);
10199 Local<v8::Object> instance = t->GetFunction()->NewInstance();
10201 Local<v8::Value> a1 =
10202 instance->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10203 CHECK(a1->StrictEquals(instance));
10204 Local<v8::Value> a2 = instance->CallAsFunction(v8::Null(isolate), 0, NULL);
10205 CHECK(a2->StrictEquals(instance));
10206 Local<v8::Value> a3 = instance->CallAsFunction(v8_num(42), 0, NULL);
10207 CHECK(a3->StrictEquals(instance));
10208 Local<v8::Value> a4 = instance->CallAsFunction(v8_str("hello"), 0, NULL);
10209 CHECK(a4->StrictEquals(instance));
10210 Local<v8::Value> a5 = instance->CallAsFunction(v8::True(isolate), 0, NULL);
10211 CHECK(a5->StrictEquals(instance));
10216 "function ReturnThisSloppy() {"
10219 "function ReturnThisStrict() {"
10223 Local<Function> ReturnThisSloppy = Local<Function>::Cast(
10224 context->Global()->Get(v8_str("ReturnThisSloppy")));
10225 Local<Function> ReturnThisStrict = Local<Function>::Cast(
10226 context->Global()->Get(v8_str("ReturnThisStrict")));
10228 Local<v8::Value> a1 =
10229 ReturnThisSloppy->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10230 CHECK(a1->StrictEquals(context->Global()));
10231 Local<v8::Value> a2 =
10232 ReturnThisSloppy->CallAsFunction(v8::Null(isolate), 0, NULL);
10233 CHECK(a2->StrictEquals(context->Global()));
10234 Local<v8::Value> a3 = ReturnThisSloppy->CallAsFunction(v8_num(42), 0, NULL);
10235 CHECK(a3->IsNumberObject());
10236 CHECK_EQ(42.0, a3.As<v8::NumberObject>()->ValueOf());
10237 Local<v8::Value> a4 =
10238 ReturnThisSloppy->CallAsFunction(v8_str("hello"), 0, NULL);
10239 CHECK(a4->IsStringObject());
10240 CHECK(a4.As<v8::StringObject>()->ValueOf()->StrictEquals(v8_str("hello")));
10241 Local<v8::Value> a5 =
10242 ReturnThisSloppy->CallAsFunction(v8::True(isolate), 0, NULL);
10243 CHECK(a5->IsBooleanObject());
10244 CHECK(a5.As<v8::BooleanObject>()->ValueOf());
10246 Local<v8::Value> a6 =
10247 ReturnThisStrict->CallAsFunction(v8::Undefined(isolate), 0, NULL);
10248 CHECK(a6->IsUndefined());
10249 Local<v8::Value> a7 =
10250 ReturnThisStrict->CallAsFunction(v8::Null(isolate), 0, NULL);
10251 CHECK(a7->IsNull());
10252 Local<v8::Value> a8 = ReturnThisStrict->CallAsFunction(v8_num(42), 0, NULL);
10253 CHECK(a8->StrictEquals(v8_num(42)));
10254 Local<v8::Value> a9 =
10255 ReturnThisStrict->CallAsFunction(v8_str("hello"), 0, NULL);
10256 CHECK(a9->StrictEquals(v8_str("hello")));
10257 Local<v8::Value> a10 =
10258 ReturnThisStrict->CallAsFunction(v8::True(isolate), 0, NULL);
10259 CHECK(a10->StrictEquals(v8::True(isolate)));
10264 // Check whether a non-function object is callable.
10265 THREADED_TEST(CallableObject) {
10266 LocalContext context;
10267 v8::Isolate* isolate = context->GetIsolate();
10268 v8::HandleScope scope(isolate);
10271 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10272 instance_template->SetCallAsFunctionHandler(call_as_function);
10273 Local<Object> instance = instance_template->NewInstance();
10274 v8::TryCatch try_catch(isolate);
10276 CHECK(instance->IsCallable());
10277 CHECK(!try_catch.HasCaught());
10281 Local<ObjectTemplate> instance_template = ObjectTemplate::New(isolate);
10282 Local<Object> instance = instance_template->NewInstance();
10283 v8::TryCatch try_catch(isolate);
10285 CHECK(!instance->IsCallable());
10286 CHECK(!try_catch.HasCaught());
10290 Local<FunctionTemplate> function_template =
10291 FunctionTemplate::New(isolate, call_as_function);
10292 Local<Function> function = function_template->GetFunction();
10293 Local<Object> instance = function;
10294 v8::TryCatch try_catch(isolate);
10296 CHECK(instance->IsCallable());
10297 CHECK(!try_catch.HasCaught());
10301 Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate);
10302 Local<Function> function = function_template->GetFunction();
10303 Local<Object> instance = function;
10304 v8::TryCatch try_catch(isolate);
10306 CHECK(instance->IsCallable());
10307 CHECK(!try_catch.HasCaught());
10312 static int Recurse(v8::Isolate* isolate, int depth, int iterations) {
10313 v8::HandleScope scope(isolate);
10314 if (depth == 0) return v8::HandleScope::NumberOfHandles(isolate);
10315 for (int i = 0; i < iterations; i++) {
10316 Local<v8::Number> n(v8::Integer::New(isolate, 42));
10318 return Recurse(isolate, depth - 1, iterations);
10322 THREADED_TEST(HandleIteration) {
10323 static const int kIterations = 500;
10324 static const int kNesting = 200;
10325 LocalContext context;
10326 v8::Isolate* isolate = context->GetIsolate();
10327 v8::HandleScope scope0(isolate);
10328 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10330 v8::HandleScope scope1(isolate);
10331 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10332 for (int i = 0; i < kIterations; i++) {
10333 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10334 CHECK_EQ(i + 1, v8::HandleScope::NumberOfHandles(isolate));
10337 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10339 v8::HandleScope scope2(CcTest::isolate());
10340 for (int j = 0; j < kIterations; j++) {
10341 Local<v8::Number> n(v8::Integer::New(CcTest::isolate(), 42));
10342 CHECK_EQ(j + 1 + kIterations,
10343 v8::HandleScope::NumberOfHandles(isolate));
10346 CHECK_EQ(kIterations, v8::HandleScope::NumberOfHandles(isolate));
10348 CHECK_EQ(0, v8::HandleScope::NumberOfHandles(isolate));
10349 CHECK_EQ(kNesting * kIterations, Recurse(isolate, kNesting, kIterations));
10353 static void InterceptorCallICFastApi(
10354 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
10355 ApiTestFuzzer::Fuzz();
10356 CheckReturnValue(info, FUNCTION_ADDR(InterceptorCallICFastApi));
10358 reinterpret_cast<int*>(v8::External::Cast(*info.Data())->Value());
10360 if ((*call_count) % 20 == 0) {
10361 CcTest::heap()->CollectAllGarbage();
10365 static void FastApiCallback_TrivialSignature(
10366 const v8::FunctionCallbackInfo<v8::Value>& args) {
10367 ApiTestFuzzer::Fuzz();
10368 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_TrivialSignature));
10369 v8::Isolate* isolate = CcTest::isolate();
10370 CHECK_EQ(isolate, args.GetIsolate());
10371 CHECK(args.This()->Equals(args.Holder()));
10372 CHECK(args.Data()->Equals(v8_str("method_data")));
10373 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10376 static void FastApiCallback_SimpleSignature(
10377 const v8::FunctionCallbackInfo<v8::Value>& args) {
10378 ApiTestFuzzer::Fuzz();
10379 CheckReturnValue(args, FUNCTION_ADDR(FastApiCallback_SimpleSignature));
10380 v8::Isolate* isolate = CcTest::isolate();
10381 CHECK_EQ(isolate, args.GetIsolate());
10382 CHECK(args.This()->GetPrototype()->Equals(args.Holder()));
10383 CHECK(args.Data()->Equals(v8_str("method_data")));
10384 // Note, we're using HasRealNamedProperty instead of Has to avoid
10385 // invoking the interceptor again.
10386 CHECK(args.Holder()->HasRealNamedProperty(v8_str("foo")));
10387 args.GetReturnValue().Set(args[0]->Int32Value() + 1);
10391 // Helper to maximize the odds of object moving.
10392 static void GenerateSomeGarbage() {
10395 "for (var i = 0; i < 1000; i++) {"
10396 " garbage = [1/i, \"garbage\" + i, garbage, {foo: garbage}];"
10398 "garbage = undefined;");
10402 void DirectApiCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
10403 static int count = 0;
10404 if (count++ % 3 == 0) {
10405 CcTest::heap()->CollectAllGarbage();
10406 // This should move the stub
10407 GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
10412 THREADED_TEST(CallICFastApi_DirectCall_GCMoveStub) {
10413 LocalContext context;
10414 v8::Isolate* isolate = context->GetIsolate();
10415 v8::HandleScope scope(isolate);
10416 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10417 v8::ObjectTemplate::New(isolate);
10418 nativeobject_templ->Set(isolate, "callback",
10419 v8::FunctionTemplate::New(isolate,
10420 DirectApiCallback));
10421 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10422 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10423 // call the api function multiple times to ensure direct call stub creation.
10426 " for (var i = 1; i <= 30; i++) {"
10427 " nativeobject.callback();"
10434 void ThrowingDirectApiCallback(
10435 const v8::FunctionCallbackInfo<v8::Value>& args) {
10436 args.GetIsolate()->ThrowException(v8_str("g"));
10440 THREADED_TEST(CallICFastApi_DirectCall_Throw) {
10441 LocalContext context;
10442 v8::Isolate* isolate = context->GetIsolate();
10443 v8::HandleScope scope(isolate);
10444 v8::Handle<v8::ObjectTemplate> nativeobject_templ =
10445 v8::ObjectTemplate::New(isolate);
10446 nativeobject_templ->Set(isolate, "callback",
10447 v8::FunctionTemplate::New(isolate,
10448 ThrowingDirectApiCallback));
10449 v8::Local<v8::Object> nativeobject_obj = nativeobject_templ->NewInstance();
10450 context->Global()->Set(v8_str("nativeobject"), nativeobject_obj);
10451 // call the api function multiple times to ensure direct call stub creation.
10452 v8::Handle<Value> result = CompileRun(
10455 " for (var i = 1; i <= 5; i++) {"
10456 " try { nativeobject.callback(); } catch (e) { result += e; }"
10460 CHECK(v8_str("ggggg")->Equals(result));
10464 static int p_getter_count_3;
10467 static Handle<Value> DoDirectGetter() {
10468 if (++p_getter_count_3 % 3 == 0) {
10469 CcTest::heap()->CollectAllGarbage();
10470 GenerateSomeGarbage();
10472 return v8_str("Direct Getter Result");
10476 static void DirectGetterCallback(
10477 Local<String> name,
10478 const v8::PropertyCallbackInfo<v8::Value>& info) {
10479 CheckReturnValue(info, FUNCTION_ADDR(DirectGetterCallback));
10480 info.GetReturnValue().Set(DoDirectGetter());
10484 template<typename Accessor>
10485 static void LoadICFastApi_DirectCall_GCMoveStub(Accessor accessor) {
10486 LocalContext context;
10487 v8::Isolate* isolate = context->GetIsolate();
10488 v8::HandleScope scope(isolate);
10489 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10490 obj->SetAccessor(v8_str("p1"), accessor);
10491 context->Global()->Set(v8_str("o1"), obj->NewInstance());
10492 p_getter_count_3 = 0;
10493 v8::Handle<v8::Value> result = CompileRun(
10495 " for (var i = 0; i < 30; i++) o1.p1;"
10499 CHECK(v8_str("Direct Getter Result")->Equals(result));
10500 CHECK_EQ(31, p_getter_count_3);
10504 THREADED_PROFILED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
10505 LoadICFastApi_DirectCall_GCMoveStub(DirectGetterCallback);
10509 void ThrowingDirectGetterCallback(
10510 Local<String> name,
10511 const v8::PropertyCallbackInfo<v8::Value>& info) {
10512 info.GetIsolate()->ThrowException(v8_str("g"));
10516 THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
10517 LocalContext context;
10518 v8::Isolate* isolate = context->GetIsolate();
10519 v8::HandleScope scope(isolate);
10520 v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New(isolate);
10521 obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
10522 context->Global()->Set(v8_str("o1"), obj->NewInstance());
10523 v8::Handle<Value> result = CompileRun(
10525 "for (var i = 0; i < 5; i++) {"
10526 " try { o1.p1; } catch (e) { result += e; }"
10529 CHECK(v8_str("ggggg")->Equals(result));
10533 THREADED_PROFILED_TEST(InterceptorCallICFastApi_TrivialSignature) {
10534 int interceptor_call_count = 0;
10535 v8::Isolate* isolate = CcTest::isolate();
10536 v8::HandleScope scope(isolate);
10537 v8::Handle<v8::FunctionTemplate> fun_templ =
10538 v8::FunctionTemplate::New(isolate);
10539 v8::Handle<v8::FunctionTemplate> method_templ =
10540 v8::FunctionTemplate::New(isolate,
10541 FastApiCallback_TrivialSignature,
10542 v8_str("method_data"),
10543 v8::Handle<v8::Signature>());
10544 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10545 proto_templ->Set(v8_str("method"), method_templ);
10546 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10547 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10548 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10549 v8::External::New(isolate, &interceptor_call_count)));
10550 LocalContext context;
10551 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10552 GenerateSomeGarbage();
10553 context->Global()->Set(v8_str("o"), fun->NewInstance());
10556 "for (var i = 0; i < 100; i++) {"
10557 " result = o.method(41);"
10559 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10560 CHECK_EQ(100, interceptor_call_count);
10564 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature) {
10565 int interceptor_call_count = 0;
10566 v8::Isolate* isolate = CcTest::isolate();
10567 v8::HandleScope scope(isolate);
10568 v8::Handle<v8::FunctionTemplate> fun_templ =
10569 v8::FunctionTemplate::New(isolate);
10570 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10571 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10572 v8::Signature::New(isolate, fun_templ));
10573 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10574 proto_templ->Set(v8_str("method"), method_templ);
10575 fun_templ->SetHiddenPrototype(true);
10576 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10577 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10578 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10579 v8::External::New(isolate, &interceptor_call_count)));
10580 LocalContext context;
10581 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10582 GenerateSomeGarbage();
10583 context->Global()->Set(v8_str("o"), fun->NewInstance());
10586 "var receiver = {};"
10587 "receiver.__proto__ = o;"
10589 "for (var i = 0; i < 100; i++) {"
10590 " result = receiver.method(41);"
10592 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10593 CHECK_EQ(100, interceptor_call_count);
10597 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss1) {
10598 int interceptor_call_count = 0;
10599 v8::Isolate* isolate = CcTest::isolate();
10600 v8::HandleScope scope(isolate);
10601 v8::Handle<v8::FunctionTemplate> fun_templ =
10602 v8::FunctionTemplate::New(isolate);
10603 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10604 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10605 v8::Signature::New(isolate, fun_templ));
10606 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10607 proto_templ->Set(v8_str("method"), method_templ);
10608 fun_templ->SetHiddenPrototype(true);
10609 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10610 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10611 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10612 v8::External::New(isolate, &interceptor_call_count)));
10613 LocalContext context;
10614 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10615 GenerateSomeGarbage();
10616 context->Global()->Set(v8_str("o"), fun->NewInstance());
10619 "var receiver = {};"
10620 "receiver.__proto__ = o;"
10622 "var saved_result = 0;"
10623 "for (var i = 0; i < 100; i++) {"
10624 " result = receiver.method(41);"
10626 " saved_result = result;"
10627 " receiver = {method: function(x) { return x - 1 }};"
10630 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10631 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10632 CHECK_GE(interceptor_call_count, 50);
10636 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
10637 int interceptor_call_count = 0;
10638 v8::Isolate* isolate = CcTest::isolate();
10639 v8::HandleScope scope(isolate);
10640 v8::Handle<v8::FunctionTemplate> fun_templ =
10641 v8::FunctionTemplate::New(isolate);
10642 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10643 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10644 v8::Signature::New(isolate, fun_templ));
10645 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10646 proto_templ->Set(v8_str("method"), method_templ);
10647 fun_templ->SetHiddenPrototype(true);
10648 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10649 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10650 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10651 v8::External::New(isolate, &interceptor_call_count)));
10652 LocalContext context;
10653 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10654 GenerateSomeGarbage();
10655 context->Global()->Set(v8_str("o"), fun->NewInstance());
10658 "var receiver = {};"
10659 "receiver.__proto__ = o;"
10661 "var saved_result = 0;"
10662 "for (var i = 0; i < 100; i++) {"
10663 " result = receiver.method(41);"
10665 " saved_result = result;"
10666 " o.method = function(x) { return x - 1 };"
10669 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10670 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10671 CHECK_GE(interceptor_call_count, 50);
10675 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
10676 int interceptor_call_count = 0;
10677 v8::Isolate* isolate = CcTest::isolate();
10678 v8::HandleScope scope(isolate);
10679 v8::Handle<v8::FunctionTemplate> fun_templ =
10680 v8::FunctionTemplate::New(isolate);
10681 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10682 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10683 v8::Signature::New(isolate, fun_templ));
10684 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10685 proto_templ->Set(v8_str("method"), method_templ);
10686 fun_templ->SetHiddenPrototype(true);
10687 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10688 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10689 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10690 v8::External::New(isolate, &interceptor_call_count)));
10691 LocalContext context;
10692 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10693 GenerateSomeGarbage();
10694 context->Global()->Set(v8_str("o"), fun->NewInstance());
10695 v8::TryCatch try_catch(isolate);
10698 "var receiver = {};"
10699 "receiver.__proto__ = o;"
10701 "var saved_result = 0;"
10702 "for (var i = 0; i < 100; i++) {"
10703 " result = receiver.method(41);"
10705 " saved_result = result;"
10709 CHECK(try_catch.HasCaught());
10710 // TODO(verwaest): Adjust message.
10711 CHECK(v8_str("TypeError: receiver.method is not a function")
10712 ->Equals(try_catch.Exception()->ToString(isolate)));
10713 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10714 CHECK_GE(interceptor_call_count, 50);
10718 THREADED_PROFILED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
10719 int interceptor_call_count = 0;
10720 v8::Isolate* isolate = CcTest::isolate();
10721 v8::HandleScope scope(isolate);
10722 v8::Handle<v8::FunctionTemplate> fun_templ =
10723 v8::FunctionTemplate::New(isolate);
10724 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10725 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10726 v8::Signature::New(isolate, fun_templ));
10727 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10728 proto_templ->Set(v8_str("method"), method_templ);
10729 fun_templ->SetHiddenPrototype(true);
10730 v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
10731 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
10732 InterceptorCallICFastApi, NULL, NULL, NULL, NULL,
10733 v8::External::New(isolate, &interceptor_call_count)));
10734 LocalContext context;
10735 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10736 GenerateSomeGarbage();
10737 context->Global()->Set(v8_str("o"), fun->NewInstance());
10738 v8::TryCatch try_catch(isolate);
10741 "var receiver = {};"
10742 "receiver.__proto__ = o;"
10744 "var saved_result = 0;"
10745 "for (var i = 0; i < 100; i++) {"
10746 " result = receiver.method(41);"
10748 " saved_result = result;"
10749 " receiver = {method: receiver.method};"
10752 CHECK(try_catch.HasCaught());
10753 CHECK(v8_str("TypeError: Illegal invocation")
10754 ->Equals(try_catch.Exception()->ToString(isolate)));
10755 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10756 CHECK_GE(interceptor_call_count, 50);
10760 THREADED_PROFILED_TEST(CallICFastApi_TrivialSignature) {
10761 v8::Isolate* isolate = CcTest::isolate();
10762 v8::HandleScope scope(isolate);
10763 v8::Handle<v8::FunctionTemplate> fun_templ =
10764 v8::FunctionTemplate::New(isolate);
10765 v8::Handle<v8::FunctionTemplate> method_templ =
10766 v8::FunctionTemplate::New(isolate,
10767 FastApiCallback_TrivialSignature,
10768 v8_str("method_data"),
10769 v8::Handle<v8::Signature>());
10770 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10771 proto_templ->Set(v8_str("method"), method_templ);
10772 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10774 LocalContext context;
10775 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10776 GenerateSomeGarbage();
10777 context->Global()->Set(v8_str("o"), fun->NewInstance());
10780 "for (var i = 0; i < 100; i++) {"
10781 " result = o.method(41);"
10784 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10788 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature) {
10789 v8::Isolate* isolate = CcTest::isolate();
10790 v8::HandleScope scope(isolate);
10791 v8::Handle<v8::FunctionTemplate> fun_templ =
10792 v8::FunctionTemplate::New(isolate);
10793 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10794 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10795 v8::Signature::New(isolate, fun_templ));
10796 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10797 proto_templ->Set(v8_str("method"), method_templ);
10798 fun_templ->SetHiddenPrototype(true);
10799 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10800 CHECK(!templ.IsEmpty());
10801 LocalContext context;
10802 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10803 GenerateSomeGarbage();
10804 context->Global()->Set(v8_str("o"), fun->NewInstance());
10807 "var receiver = {};"
10808 "receiver.__proto__ = o;"
10810 "for (var i = 0; i < 100; i++) {"
10811 " result = receiver.method(41);"
10814 CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
10818 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss1) {
10819 v8::Isolate* isolate = CcTest::isolate();
10820 v8::HandleScope scope(isolate);
10821 v8::Handle<v8::FunctionTemplate> fun_templ =
10822 v8::FunctionTemplate::New(isolate);
10823 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10824 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10825 v8::Signature::New(isolate, fun_templ));
10826 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10827 proto_templ->Set(v8_str("method"), method_templ);
10828 fun_templ->SetHiddenPrototype(true);
10829 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10830 CHECK(!templ.IsEmpty());
10831 LocalContext context;
10832 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10833 GenerateSomeGarbage();
10834 context->Global()->Set(v8_str("o"), fun->NewInstance());
10837 "var receiver = {};"
10838 "receiver.__proto__ = o;"
10840 "var saved_result = 0;"
10841 "for (var i = 0; i < 100; i++) {"
10842 " result = receiver.method(41);"
10844 " saved_result = result;"
10845 " receiver = {method: function(x) { return x - 1 }};"
10848 CHECK_EQ(40, context->Global()->Get(v8_str("result"))->Int32Value());
10849 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10853 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_Miss2) {
10854 v8::Isolate* isolate = CcTest::isolate();
10855 v8::HandleScope scope(isolate);
10856 v8::Handle<v8::FunctionTemplate> fun_templ =
10857 v8::FunctionTemplate::New(isolate);
10858 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10859 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10860 v8::Signature::New(isolate, fun_templ));
10861 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10862 proto_templ->Set(v8_str("method"), method_templ);
10863 fun_templ->SetHiddenPrototype(true);
10864 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10865 CHECK(!templ.IsEmpty());
10866 LocalContext context;
10867 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10868 GenerateSomeGarbage();
10869 context->Global()->Set(v8_str("o"), fun->NewInstance());
10870 v8::TryCatch try_catch(isolate);
10873 "var receiver = {};"
10874 "receiver.__proto__ = o;"
10876 "var saved_result = 0;"
10877 "for (var i = 0; i < 100; i++) {"
10878 " result = receiver.method(41);"
10880 " saved_result = result;"
10884 CHECK(try_catch.HasCaught());
10885 // TODO(verwaest): Adjust message.
10886 CHECK(v8_str("TypeError: receiver.method is not a function")
10887 ->Equals(try_catch.Exception()->ToString(isolate)));
10888 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10892 THREADED_PROFILED_TEST(CallICFastApi_SimpleSignature_TypeError) {
10893 v8::Isolate* isolate = CcTest::isolate();
10894 v8::HandleScope scope(isolate);
10895 v8::Handle<v8::FunctionTemplate> fun_templ =
10896 v8::FunctionTemplate::New(isolate);
10897 v8::Handle<v8::FunctionTemplate> method_templ = v8::FunctionTemplate::New(
10898 isolate, FastApiCallback_SimpleSignature, v8_str("method_data"),
10899 v8::Signature::New(isolate, fun_templ));
10900 v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
10901 proto_templ->Set(v8_str("method"), method_templ);
10902 fun_templ->SetHiddenPrototype(true);
10903 v8::Handle<v8::ObjectTemplate> templ(fun_templ->InstanceTemplate());
10904 CHECK(!templ.IsEmpty());
10905 LocalContext context;
10906 v8::Handle<v8::Function> fun = fun_templ->GetFunction();
10907 GenerateSomeGarbage();
10908 context->Global()->Set(v8_str("o"), fun->NewInstance());
10909 v8::TryCatch try_catch(isolate);
10912 "var receiver = {};"
10913 "receiver.__proto__ = o;"
10915 "var saved_result = 0;"
10916 "for (var i = 0; i < 100; i++) {"
10917 " result = receiver.method(41);"
10919 " saved_result = result;"
10920 " receiver = Object.create(receiver);"
10923 CHECK(try_catch.HasCaught());
10924 CHECK(v8_str("TypeError: Illegal invocation")
10925 ->Equals(try_catch.Exception()->ToString(isolate)));
10926 CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
10930 static void ThrowingGetter(Local<String> name,
10931 const v8::PropertyCallbackInfo<v8::Value>& info) {
10932 ApiTestFuzzer::Fuzz();
10933 info.GetIsolate()->ThrowException(Handle<Value>());
10934 info.GetReturnValue().SetUndefined();
10938 THREADED_TEST(VariousGetPropertiesAndThrowingCallbacks) {
10939 LocalContext context;
10940 HandleScope scope(context->GetIsolate());
10942 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
10943 Local<ObjectTemplate> instance_templ = templ->InstanceTemplate();
10944 instance_templ->SetAccessor(v8_str("f"), ThrowingGetter);
10946 Local<Object> instance = templ->GetFunction()->NewInstance();
10948 Local<Object> another = Object::New(context->GetIsolate());
10949 another->SetPrototype(instance);
10951 Local<Object> with_js_getter = CompileRun(
10953 "o.__defineGetter__('f', function() { throw undefined; });\n"
10954 "o\n").As<Object>();
10955 CHECK(!with_js_getter.IsEmpty());
10957 TryCatch try_catch(context->GetIsolate());
10959 Local<Value> result = instance->GetRealNamedProperty(v8_str("f"));
10960 CHECK(try_catch.HasCaught());
10962 CHECK(result.IsEmpty());
10964 Maybe<PropertyAttribute> attr =
10965 instance->GetRealNamedPropertyAttributes(v8_str("f"));
10966 CHECK(!try_catch.HasCaught());
10967 CHECK(Just(None) == attr);
10969 result = another->GetRealNamedProperty(v8_str("f"));
10970 CHECK(try_catch.HasCaught());
10972 CHECK(result.IsEmpty());
10974 attr = another->GetRealNamedPropertyAttributes(v8_str("f"));
10975 CHECK(!try_catch.HasCaught());
10976 CHECK(Just(None) == attr);
10978 result = another->GetRealNamedPropertyInPrototypeChain(v8_str("f"));
10979 CHECK(try_catch.HasCaught());
10981 CHECK(result.IsEmpty());
10983 attr = another->GetRealNamedPropertyAttributesInPrototypeChain(v8_str("f"));
10984 CHECK(!try_catch.HasCaught());
10985 CHECK(Just(None) == attr);
10987 result = another->Get(v8_str("f"));
10988 CHECK(try_catch.HasCaught());
10990 CHECK(result.IsEmpty());
10992 result = with_js_getter->GetRealNamedProperty(v8_str("f"));
10993 CHECK(try_catch.HasCaught());
10995 CHECK(result.IsEmpty());
10997 attr = with_js_getter->GetRealNamedPropertyAttributes(v8_str("f"));
10998 CHECK(!try_catch.HasCaught());
10999 CHECK(Just(None) == attr);
11001 result = with_js_getter->Get(v8_str("f"));
11002 CHECK(try_catch.HasCaught());
11004 CHECK(result.IsEmpty());
11008 static void ThrowingCallbackWithTryCatch(
11009 const v8::FunctionCallbackInfo<v8::Value>& args) {
11010 TryCatch try_catch(args.GetIsolate());
11011 // Verboseness is important: it triggers message delivery which can call into
11013 try_catch.SetVerbose(true);
11014 CompileRun("throw 'from JS';");
11015 CHECK(try_catch.HasCaught());
11016 CHECK(!CcTest::i_isolate()->has_pending_exception());
11017 CHECK(!CcTest::i_isolate()->has_scheduled_exception());
11021 static int call_depth;
11024 static void WithTryCatch(Handle<Message> message, Handle<Value> data) {
11025 TryCatch try_catch(CcTest::isolate());
11029 static void ThrowFromJS(Handle<Message> message, Handle<Value> data) {
11030 if (--call_depth) CompileRun("throw 'ThrowInJS';");
11034 static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
11035 if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
11039 static void WebKitLike(Handle<Message> message, Handle<Value> data) {
11040 Handle<String> errorMessageString = message->Get();
11041 CHECK(!errorMessageString.IsEmpty());
11042 message->GetStackTrace();
11043 message->GetScriptOrigin().ResourceName();
11047 THREADED_TEST(ExceptionsDoNotPropagatePastTryCatch) {
11048 LocalContext context;
11049 v8::Isolate* isolate = context->GetIsolate();
11050 HandleScope scope(isolate);
11052 Local<Function> func =
11053 FunctionTemplate::New(isolate,
11054 ThrowingCallbackWithTryCatch)->GetFunction();
11055 context->Global()->Set(v8_str("func"), func);
11057 MessageCallback callbacks[] =
11058 { NULL, WebKitLike, ThrowViaApi, ThrowFromJS, WithTryCatch };
11059 for (unsigned i = 0; i < sizeof(callbacks)/sizeof(callbacks[0]); i++) {
11060 MessageCallback callback = callbacks[i];
11061 if (callback != NULL) {
11062 V8::AddMessageListener(callback);
11064 // Some small number to control number of times message handler should
11065 // throw an exception.
11068 "var thrown = false;\n"
11069 "try { func(); } catch(e) { thrown = true; }\n"
11071 if (callback != NULL) {
11072 V8::RemoveMessageListeners(callback);
11078 static void ParentGetter(Local<String> name,
11079 const v8::PropertyCallbackInfo<v8::Value>& info) {
11080 ApiTestFuzzer::Fuzz();
11081 info.GetReturnValue().Set(v8_num(1));
11085 static void ChildGetter(Local<String> name,
11086 const v8::PropertyCallbackInfo<v8::Value>& info) {
11087 ApiTestFuzzer::Fuzz();
11088 info.GetReturnValue().Set(v8_num(42));
11092 THREADED_TEST(Overriding) {
11093 LocalContext context;
11094 v8::Isolate* isolate = context->GetIsolate();
11095 v8::HandleScope scope(isolate);
11097 // Parent template.
11098 Local<v8::FunctionTemplate> parent_templ = v8::FunctionTemplate::New(isolate);
11099 Local<ObjectTemplate> parent_instance_templ =
11100 parent_templ->InstanceTemplate();
11101 parent_instance_templ->SetAccessor(v8_str("f"), ParentGetter);
11103 // Template that inherits from the parent template.
11104 Local<v8::FunctionTemplate> child_templ = v8::FunctionTemplate::New(isolate);
11105 Local<ObjectTemplate> child_instance_templ =
11106 child_templ->InstanceTemplate();
11107 child_templ->Inherit(parent_templ);
11108 // Override 'f'. The child version of 'f' should get called for child
11110 child_instance_templ->SetAccessor(v8_str("f"), ChildGetter);
11111 // Add 'g' twice. The 'g' added last should get called for instances.
11112 child_instance_templ->SetAccessor(v8_str("g"), ParentGetter);
11113 child_instance_templ->SetAccessor(v8_str("g"), ChildGetter);
11115 // Add 'h' as an accessor to the proto template with ReadOnly attributes
11116 // so 'h' can be shadowed on the instance object.
11117 Local<ObjectTemplate> child_proto_templ = child_templ->PrototypeTemplate();
11118 child_proto_templ->SetAccessor(v8_str("h"), ParentGetter, 0,
11119 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11121 // Add 'i' as an accessor to the instance template with ReadOnly attributes
11122 // but the attribute does not have effect because it is duplicated with
11124 child_instance_templ->SetAccessor(v8_str("i"), ChildGetter, 0,
11125 v8::Handle<Value>(), v8::DEFAULT, v8::ReadOnly);
11129 // Instantiate the child template.
11130 Local<v8::Object> instance = child_templ->GetFunction()->NewInstance();
11132 // Check that the child function overrides the parent one.
11133 context->Global()->Set(v8_str("o"), instance);
11134 Local<Value> value = v8_compile("o.f")->Run();
11135 // Check that the 'g' that was added last is hit.
11136 CHECK_EQ(42, value->Int32Value());
11137 value = v8_compile("o.g")->Run();
11138 CHECK_EQ(42, value->Int32Value());
11140 // Check that 'h' cannot be shadowed.
11141 value = v8_compile("o.h = 3; o.h")->Run();
11142 CHECK_EQ(1, value->Int32Value());
11144 // Check that 'i' cannot be shadowed or changed.
11145 value = v8_compile("o.i = 3; o.i")->Run();
11146 CHECK_EQ(42, value->Int32Value());
11150 static void IsConstructHandler(
11151 const v8::FunctionCallbackInfo<v8::Value>& args) {
11152 ApiTestFuzzer::Fuzz();
11153 args.GetReturnValue().Set(args.IsConstructCall());
11157 THREADED_TEST(IsConstructCall) {
11158 v8::Isolate* isolate = CcTest::isolate();
11159 v8::HandleScope scope(isolate);
11161 // Function template with call handler.
11162 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11163 templ->SetCallHandler(IsConstructHandler);
11165 LocalContext context;
11167 context->Global()->Set(v8_str("f"), templ->GetFunction());
11168 Local<Value> value = v8_compile("f()")->Run();
11169 CHECK(!value->BooleanValue());
11170 value = v8_compile("new f()")->Run();
11171 CHECK(value->BooleanValue());
11175 THREADED_TEST(ObjectProtoToString) {
11176 v8::Isolate* isolate = CcTest::isolate();
11177 v8::HandleScope scope(isolate);
11178 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11179 templ->SetClassName(v8_str("MyClass"));
11181 LocalContext context;
11183 Local<String> customized_tostring = v8_str("customized toString");
11185 // Replace Object.prototype.toString
11186 v8_compile("Object.prototype.toString = function() {"
11187 " return 'customized toString';"
11190 // Normal ToString call should call replaced Object.prototype.toString
11191 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11192 Local<String> value = instance->ToString(isolate);
11193 CHECK(value->IsString() && value->Equals(customized_tostring));
11195 // ObjectProtoToString should not call replace toString function.
11196 value = instance->ObjectProtoToString();
11197 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11200 value = context->Global()->ObjectProtoToString();
11201 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11203 // Check ordinary object
11204 Local<Value> object = v8_compile("new Object()")->Run();
11205 value = object.As<v8::Object>()->ObjectProtoToString();
11206 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11210 TEST(ObjectProtoToStringES6) {
11211 // TODO(dslomov, caitp): merge into ObjectProtoToString test once shipped.
11212 i::FLAG_harmony_tostring = true;
11213 LocalContext context;
11214 v8::Isolate* isolate = CcTest::isolate();
11215 v8::HandleScope scope(isolate);
11216 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
11217 templ->SetClassName(v8_str("MyClass"));
11219 Local<String> customized_tostring = v8_str("customized toString");
11221 // Replace Object.prototype.toString
11223 "Object.prototype.toString = function() {"
11224 " return 'customized toString';"
11227 // Normal ToString call should call replaced Object.prototype.toString
11228 Local<v8::Object> instance = templ->GetFunction()->NewInstance();
11229 Local<String> value = instance->ToString(isolate);
11230 CHECK(value->IsString() && value->Equals(customized_tostring));
11232 // ObjectProtoToString should not call replace toString function.
11233 value = instance->ObjectProtoToString();
11234 CHECK(value->IsString() && value->Equals(v8_str("[object MyClass]")));
11237 value = context->Global()->ObjectProtoToString();
11238 CHECK(value->IsString() && value->Equals(v8_str("[object global]")));
11240 // Check ordinary object
11241 Local<Value> object = CompileRun("new Object()");
11242 value = object.As<v8::Object>()->ObjectProtoToString();
11243 CHECK(value->IsString() && value->Equals(v8_str("[object Object]")));
11245 // Check that ES6 semantics using @@toStringTag work
11246 Local<v8::Symbol> toStringTag = v8::Symbol::GetToStringTag(isolate);
11248 #define TEST_TOSTRINGTAG(type, tag, expected) \
11250 object = CompileRun("new " #type "()"); \
11251 object.As<v8::Object>()->Set(toStringTag, v8_str(#tag)); \
11252 value = object.As<v8::Object>()->ObjectProtoToString(); \
11253 CHECK(value->IsString() && \
11254 value->Equals(v8_str("[object " #expected "]"))); \
11257 TEST_TOSTRINGTAG(Array, Object, Object);
11258 TEST_TOSTRINGTAG(Object, Arguments, Arguments);
11259 TEST_TOSTRINGTAG(Object, Array, Array);
11260 TEST_TOSTRINGTAG(Object, Boolean, Boolean);
11261 TEST_TOSTRINGTAG(Object, Date, Date);
11262 TEST_TOSTRINGTAG(Object, Error, Error);
11263 TEST_TOSTRINGTAG(Object, Function, Function);
11264 TEST_TOSTRINGTAG(Object, Number, Number);
11265 TEST_TOSTRINGTAG(Object, RegExp, RegExp);
11266 TEST_TOSTRINGTAG(Object, String, String);
11267 TEST_TOSTRINGTAG(Object, Foo, Foo);
11269 #undef TEST_TOSTRINGTAG
11271 Local<v8::RegExp> valueRegExp = v8::RegExp::New(v8_str("^$"),
11272 v8::RegExp::kNone);
11273 Local<Value> valueNumber = v8_num(123);
11274 Local<v8::Symbol> valueSymbol = v8_symbol("TestSymbol");
11275 Local<v8::Function> valueFunction =
11276 CompileRun("(function fn() {})").As<v8::Function>();
11277 Local<v8::Object> valueObject = v8::Object::New(v8::Isolate::GetCurrent());
11278 Local<v8::Primitive> valueNull = v8::Null(v8::Isolate::GetCurrent());
11279 Local<v8::Primitive> valueUndef = v8::Undefined(v8::Isolate::GetCurrent());
11281 #define TEST_TOSTRINGTAG(type, tagValue, expected) \
11283 object = CompileRun("new " #type "()"); \
11284 object.As<v8::Object>()->Set(toStringTag, tagValue); \
11285 value = object.As<v8::Object>()->ObjectProtoToString(); \
11286 CHECK(value->IsString() && \
11287 value->Equals(v8_str("[object " #expected "]"))); \
11290 #define TEST_TOSTRINGTAG_TYPES(tagValue) \
11291 TEST_TOSTRINGTAG(Array, tagValue, Array); \
11292 TEST_TOSTRINGTAG(Object, tagValue, Object); \
11293 TEST_TOSTRINGTAG(Function, tagValue, Function); \
11294 TEST_TOSTRINGTAG(Date, tagValue, Date); \
11295 TEST_TOSTRINGTAG(RegExp, tagValue, RegExp); \
11296 TEST_TOSTRINGTAG(Error, tagValue, Error); \
11298 // Test non-String-valued @@toStringTag
11299 TEST_TOSTRINGTAG_TYPES(valueRegExp);
11300 TEST_TOSTRINGTAG_TYPES(valueNumber);
11301 TEST_TOSTRINGTAG_TYPES(valueSymbol);
11302 TEST_TOSTRINGTAG_TYPES(valueFunction);
11303 TEST_TOSTRINGTAG_TYPES(valueObject);
11304 TEST_TOSTRINGTAG_TYPES(valueNull);
11305 TEST_TOSTRINGTAG_TYPES(valueUndef);
11307 #undef TEST_TOSTRINGTAG
11308 #undef TEST_TOSTRINGTAG_TYPES
11310 // @@toStringTag getter throws
11311 Local<Value> obj = v8::Object::New(isolate);
11312 obj.As<v8::Object>()->SetAccessor(toStringTag, ThrowingSymbolAccessorGetter);
11314 TryCatch try_catch(isolate);
11315 value = obj.As<v8::Object>()->ObjectProtoToString();
11316 CHECK(value.IsEmpty());
11317 CHECK(try_catch.HasCaught());
11320 // @@toStringTag getter does not throw
11321 obj = v8::Object::New(isolate);
11322 obj.As<v8::Object>()->SetAccessor(
11323 toStringTag, SymbolAccessorGetterReturnsDefault, 0, v8_str("Test"));
11325 TryCatch try_catch(isolate);
11326 value = obj.As<v8::Object>()->ObjectProtoToString();
11327 CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11328 CHECK(!try_catch.HasCaught());
11331 // JS @@toStringTag value
11332 obj = CompileRun("obj = {}; obj[Symbol.toStringTag] = 'Test'; obj");
11334 TryCatch try_catch(isolate);
11335 value = obj.As<v8::Object>()->ObjectProtoToString();
11336 CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11337 CHECK(!try_catch.HasCaught());
11340 // JS @@toStringTag getter throws
11342 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11343 " get: function() { throw 'Test'; }"
11346 TryCatch try_catch(isolate);
11347 value = obj.As<v8::Object>()->ObjectProtoToString();
11348 CHECK(value.IsEmpty());
11349 CHECK(try_catch.HasCaught());
11352 // JS @@toStringTag getter does not throw
11354 "obj = {}; Object.defineProperty(obj, Symbol.toStringTag, {"
11355 " get: function() { return 'Test'; }"
11358 TryCatch try_catch(isolate);
11359 value = obj.As<v8::Object>()->ObjectProtoToString();
11360 CHECK(value->IsString() && value->Equals(v8_str("[object Test]")));
11361 CHECK(!try_catch.HasCaught());
11366 THREADED_TEST(ObjectGetConstructorName) {
11367 v8::Isolate* isolate = CcTest::isolate();
11368 LocalContext context;
11369 v8::HandleScope scope(isolate);
11371 "function Parent() {};"
11372 "function Child() {};"
11373 "Child.prototype = new Parent();"
11374 "var outer = { inner: function() { } };"
11375 "var p = new Parent();"
11376 "var c = new Child();"
11377 "var x = new outer.inner();"
11378 "var proto = Child.prototype;")->Run();
11380 Local<v8::Value> p = context->Global()->Get(v8_str("p"));
11381 CHECK(p->IsObject() &&
11382 p->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Parent")));
11384 Local<v8::Value> c = context->Global()->Get(v8_str("c"));
11385 CHECK(c->IsObject() &&
11386 c->ToObject(isolate)->GetConstructorName()->Equals(v8_str("Child")));
11388 Local<v8::Value> x = context->Global()->Get(v8_str("x"));
11389 CHECK(x->IsObject() &&
11390 x->ToObject(isolate)->GetConstructorName()->Equals(
11391 v8_str("outer.inner")));
11393 Local<v8::Value> child_prototype = context->Global()->Get(v8_str("proto"));
11394 CHECK(child_prototype->IsObject() &&
11395 child_prototype->ToObject(isolate)->GetConstructorName()->Equals(
11396 v8_str("Parent")));
11400 bool ApiTestFuzzer::fuzzing_ = false;
11401 v8::base::Semaphore ApiTestFuzzer::all_tests_done_(0);
11402 int ApiTestFuzzer::active_tests_;
11403 int ApiTestFuzzer::tests_being_run_;
11404 int ApiTestFuzzer::current_;
11407 // We are in a callback and want to switch to another thread (if we
11408 // are currently running the thread fuzzing test).
11409 void ApiTestFuzzer::Fuzz() {
11410 if (!fuzzing_) return;
11411 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_;
11412 test->ContextSwitch();
11416 // Let the next thread go. Since it is also waiting on the V8 lock it may
11417 // not start immediately.
11418 bool ApiTestFuzzer::NextThread() {
11419 int test_position = GetNextTestNumber();
11420 const char* test_name = RegisterThreadedTest::nth(current_)->name();
11421 if (test_position == current_) {
11423 printf("Stay with %s\n", test_name);
11426 if (kLogThreading) {
11427 printf("Switch from %s to %s\n",
11429 RegisterThreadedTest::nth(test_position)->name());
11431 current_ = test_position;
11432 RegisterThreadedTest::nth(current_)->fuzzer_->gate_.Signal();
11437 void ApiTestFuzzer::Run() {
11438 // When it is our turn...
11441 // ... get the V8 lock and start running the test.
11442 v8::Locker locker(CcTest::isolate());
11445 // This test finished.
11448 // If it was the last then signal that fact.
11449 if (active_tests_ == 0) {
11450 all_tests_done_.Signal();
11452 // Otherwise select a new test and start that.
11458 static unsigned linear_congruential_generator;
11461 void ApiTestFuzzer::SetUp(PartOfTest part) {
11462 linear_congruential_generator = i::FLAG_testing_prng_seed;
11464 int count = RegisterThreadedTest::count();
11465 int start = count * part / (LAST_PART + 1);
11466 int end = (count * (part + 1) / (LAST_PART + 1)) - 1;
11467 active_tests_ = tests_being_run_ = end - start + 1;
11468 for (int i = 0; i < tests_being_run_; i++) {
11469 RegisterThreadedTest::nth(i)->fuzzer_ = new ApiTestFuzzer(i + start);
11471 for (int i = 0; i < active_tests_; i++) {
11472 RegisterThreadedTest::nth(i)->fuzzer_->Start();
11477 static void CallTestNumber(int test_number) {
11478 (RegisterThreadedTest::nth(test_number)->callback())();
11482 void ApiTestFuzzer::RunAllTests() {
11483 // Set off the first test.
11486 // Wait till they are all done.
11487 all_tests_done_.Wait();
11491 int ApiTestFuzzer::GetNextTestNumber() {
11494 next_test = (linear_congruential_generator >> 16) % tests_being_run_;
11495 linear_congruential_generator *= 1664525u;
11496 linear_congruential_generator += 1013904223u;
11497 } while (!RegisterThreadedTest::nth(next_test)->fuzzer_->active_);
11502 void ApiTestFuzzer::ContextSwitch() {
11503 // If the new thread is the same as the current thread there is nothing to do.
11504 if (NextThread()) {
11505 // Now it can start.
11506 v8::Unlocker unlocker(CcTest::isolate());
11507 // Wait till someone starts us again.
11514 void ApiTestFuzzer::TearDown() {
11516 for (int i = 0; i < RegisterThreadedTest::count(); i++) {
11517 ApiTestFuzzer *fuzzer = RegisterThreadedTest::nth(i)->fuzzer_;
11518 if (fuzzer != NULL) fuzzer->Join();
11523 // Lets not be needlessly self-referential.
11525 ApiTestFuzzer::SetUp(ApiTestFuzzer::FIRST_PART);
11526 ApiTestFuzzer::RunAllTests();
11527 ApiTestFuzzer::TearDown();
11532 ApiTestFuzzer::SetUp(ApiTestFuzzer::SECOND_PART);
11533 ApiTestFuzzer::RunAllTests();
11534 ApiTestFuzzer::TearDown();
11539 ApiTestFuzzer::SetUp(ApiTestFuzzer::THIRD_PART);
11540 ApiTestFuzzer::RunAllTests();
11541 ApiTestFuzzer::TearDown();
11546 ApiTestFuzzer::SetUp(ApiTestFuzzer::FOURTH_PART);
11547 ApiTestFuzzer::RunAllTests();
11548 ApiTestFuzzer::TearDown();
11552 void ApiTestFuzzer::CallTest() {
11553 v8::Isolate::Scope scope(CcTest::isolate());
11555 printf("Start test %d\n", test_number_);
11556 CallTestNumber(test_number_);
11558 printf("End test %d\n", test_number_);
11562 static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
11563 v8::Isolate* isolate = args.GetIsolate();
11564 CHECK(v8::Locker::IsLocked(isolate));
11565 ApiTestFuzzer::Fuzz();
11566 v8::Unlocker unlocker(isolate);
11567 const char* code = "throw 7;";
11569 v8::Locker nested_locker(isolate);
11570 v8::HandleScope scope(isolate);
11571 v8::Handle<Value> exception;
11573 v8::TryCatch try_catch(isolate);
11574 v8::Handle<Value> value = CompileRun(code);
11575 CHECK(value.IsEmpty());
11576 CHECK(try_catch.HasCaught());
11577 // Make sure to wrap the exception in a new handle because
11578 // the handle returned from the TryCatch is destroyed
11579 // when the TryCatch is destroyed.
11580 exception = Local<Value>::New(isolate, try_catch.Exception());
11582 args.GetIsolate()->ThrowException(exception);
11587 static void ThrowInJSNoCatch(const v8::FunctionCallbackInfo<v8::Value>& args) {
11588 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11589 ApiTestFuzzer::Fuzz();
11590 v8::Unlocker unlocker(CcTest::isolate());
11591 const char* code = "throw 7;";
11593 v8::Locker nested_locker(CcTest::isolate());
11594 v8::HandleScope scope(args.GetIsolate());
11595 v8::Handle<Value> value = CompileRun(code);
11596 CHECK(value.IsEmpty());
11597 args.GetReturnValue().Set(v8_str("foo"));
11602 // These are locking tests that don't need to be run again
11603 // as part of the locking aggregation tests.
11604 TEST(NestedLockers) {
11605 v8::Isolate* isolate = CcTest::isolate();
11606 v8::Locker locker(isolate);
11607 CHECK(v8::Locker::IsLocked(isolate));
11609 v8::HandleScope scope(env->GetIsolate());
11610 Local<v8::FunctionTemplate> fun_templ =
11611 v8::FunctionTemplate::New(isolate, ThrowInJS);
11612 Local<Function> fun = fun_templ->GetFunction();
11613 env->Global()->Set(v8_str("throw_in_js"), fun);
11614 Local<Script> script = v8_compile("(function () {"
11622 CHECK_EQ(91, script->Run()->Int32Value());
11626 // These are locking tests that don't need to be run again
11627 // as part of the locking aggregation tests.
11628 TEST(NestedLockersNoTryCatch) {
11629 v8::Locker locker(CcTest::isolate());
11631 v8::HandleScope scope(env->GetIsolate());
11632 Local<v8::FunctionTemplate> fun_templ =
11633 v8::FunctionTemplate::New(env->GetIsolate(), ThrowInJSNoCatch);
11634 Local<Function> fun = fun_templ->GetFunction();
11635 env->Global()->Set(v8_str("throw_in_js"), fun);
11636 Local<Script> script = v8_compile("(function () {"
11644 CHECK_EQ(91, script->Run()->Int32Value());
11648 THREADED_TEST(RecursiveLocking) {
11649 v8::Locker locker(CcTest::isolate());
11651 v8::Locker locker2(CcTest::isolate());
11652 CHECK(v8::Locker::IsLocked(CcTest::isolate()));
11657 static void UnlockForAMoment(const v8::FunctionCallbackInfo<v8::Value>& args) {
11658 ApiTestFuzzer::Fuzz();
11659 v8::Unlocker unlocker(CcTest::isolate());
11663 THREADED_TEST(LockUnlockLock) {
11665 v8::Locker locker(CcTest::isolate());
11666 v8::HandleScope scope(CcTest::isolate());
11668 Local<v8::FunctionTemplate> fun_templ =
11669 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11670 Local<Function> fun = fun_templ->GetFunction();
11671 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11672 Local<Script> script = v8_compile("(function () {"
11673 " unlock_for_a_moment();"
11676 CHECK_EQ(42, script->Run()->Int32Value());
11679 v8::Locker locker(CcTest::isolate());
11680 v8::HandleScope scope(CcTest::isolate());
11682 Local<v8::FunctionTemplate> fun_templ =
11683 v8::FunctionTemplate::New(CcTest::isolate(), UnlockForAMoment);
11684 Local<Function> fun = fun_templ->GetFunction();
11685 env->Global()->Set(v8_str("unlock_for_a_moment"), fun);
11686 Local<Script> script = v8_compile("(function () {"
11687 " unlock_for_a_moment();"
11690 CHECK_EQ(42, script->Run()->Int32Value());
11695 static int GetGlobalObjectsCount() {
11697 i::HeapIterator it(CcTest::heap());
11698 for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
11699 if (object->IsJSGlobalObject()) count++;
11700 // Subtract one to compensate for the code stub context that is always present
11705 static void CheckSurvivingGlobalObjectsCount(int expected) {
11706 // We need to collect all garbage twice to be sure that everything
11707 // has been collected. This is because inline caches are cleared in
11708 // the first garbage collection but some of the maps have already
11709 // been marked at that point. Therefore some of the maps are not
11710 // collected until the second garbage collection.
11711 CcTest::heap()->CollectAllGarbage();
11712 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
11713 int count = GetGlobalObjectsCount();
11715 if (count != expected) CcTest::heap()->TracePathToGlobal();
11717 CHECK_EQ(expected, count);
11721 TEST(DontLeakGlobalObjects) {
11722 // Regression test for issues 1139850 and 1174891.
11724 i::FLAG_expose_gc = true;
11725 v8::V8::Initialize();
11727 for (int i = 0; i < 5; i++) {
11728 { v8::HandleScope scope(CcTest::isolate());
11729 LocalContext context;
11731 CcTest::isolate()->ContextDisposedNotification();
11732 CheckSurvivingGlobalObjectsCount(0);
11734 { v8::HandleScope scope(CcTest::isolate());
11735 LocalContext context;
11736 v8_compile("Date")->Run();
11738 CcTest::isolate()->ContextDisposedNotification();
11739 CheckSurvivingGlobalObjectsCount(0);
11741 { v8::HandleScope scope(CcTest::isolate());
11742 LocalContext context;
11743 v8_compile("/aaa/")->Run();
11745 CcTest::isolate()->ContextDisposedNotification();
11746 CheckSurvivingGlobalObjectsCount(0);
11748 { v8::HandleScope scope(CcTest::isolate());
11749 const char* extension_list[] = { "v8/gc" };
11750 v8::ExtensionConfiguration extensions(1, extension_list);
11751 LocalContext context(&extensions);
11752 v8_compile("gc();")->Run();
11754 CcTest::isolate()->ContextDisposedNotification();
11755 CheckSurvivingGlobalObjectsCount(0);
11760 TEST(CopyablePersistent) {
11761 LocalContext context;
11762 v8::Isolate* isolate = context->GetIsolate();
11763 i::GlobalHandles* globals =
11764 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11765 int initial_handles = globals->global_handles_count();
11766 typedef v8::Persistent<v8::Object, v8::CopyablePersistentTraits<v8::Object> >
11769 CopyableObject handle1;
11771 v8::HandleScope scope(isolate);
11772 handle1.Reset(isolate, v8::Object::New(isolate));
11774 CHECK_EQ(initial_handles + 1, globals->global_handles_count());
11775 CopyableObject handle2;
11777 CHECK(handle1 == handle2);
11778 CHECK_EQ(initial_handles + 2, globals->global_handles_count());
11779 CopyableObject handle3(handle2);
11780 CHECK(handle1 == handle3);
11781 CHECK_EQ(initial_handles + 3, globals->global_handles_count());
11783 // Verify autodispose
11784 CHECK_EQ(initial_handles, globals->global_handles_count());
11788 static void WeakApiCallback(
11789 const v8::WeakCallbackInfo<Persistent<v8::Object>>& data) {
11790 data.GetParameter()->Reset();
11791 delete data.GetParameter();
11795 TEST(WeakCallbackApi) {
11796 LocalContext context;
11797 v8::Isolate* isolate = context->GetIsolate();
11798 i::GlobalHandles* globals =
11799 reinterpret_cast<i::Isolate*>(isolate)->global_handles();
11800 int initial_handles = globals->global_handles_count();
11802 v8::HandleScope scope(isolate);
11803 v8::Local<v8::Object> obj = v8::Object::New(isolate);
11804 obj->Set(v8_str("key"), v8::Integer::New(isolate, 231));
11805 v8::Persistent<v8::Object>* handle =
11806 new v8::Persistent<v8::Object>(isolate, obj);
11807 handle->SetWeak<v8::Persistent<v8::Object>>(
11808 handle, WeakApiCallback, v8::WeakCallbackType::kParameter);
11810 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
11811 i::Heap::kAbortIncrementalMarkingMask);
11812 // Verify disposed.
11813 CHECK_EQ(initial_handles, globals->global_handles_count());
11817 v8::Persistent<v8::Object> some_object;
11818 v8::Persistent<v8::Object> bad_handle;
11821 void NewPersistentHandleCallback2(
11822 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11823 v8::HandleScope scope(data.GetIsolate());
11824 bad_handle.Reset(data.GetIsolate(), some_object);
11828 void NewPersistentHandleCallback1(
11829 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11830 data.GetParameter()->Reset();
11831 data.SetSecondPassCallback(NewPersistentHandleCallback2);
11835 THREADED_TEST(NewPersistentHandleFromWeakCallback) {
11836 LocalContext context;
11837 v8::Isolate* isolate = context->GetIsolate();
11839 v8::Persistent<v8::Object> handle1, handle2;
11841 v8::HandleScope scope(isolate);
11842 some_object.Reset(isolate, v8::Object::New(isolate));
11843 handle1.Reset(isolate, v8::Object::New(isolate));
11844 handle2.Reset(isolate, v8::Object::New(isolate));
11846 // Note: order is implementation dependent alas: currently
11847 // global handle nodes are processed by PostGarbageCollectionProcessing
11848 // in reverse allocation order, so if second allocated handle is deleted,
11849 // weak callback of the first handle would be able to 'reallocate' it.
11850 handle1.SetWeak(&handle1, NewPersistentHandleCallback1,
11851 v8::WeakCallbackType::kParameter);
11853 CcTest::heap()->CollectAllGarbage();
11857 v8::Persistent<v8::Object> to_be_disposed;
11860 void DisposeAndForceGcCallback2(
11861 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11862 to_be_disposed.Reset();
11863 CcTest::heap()->CollectAllGarbage();
11867 void DisposeAndForceGcCallback1(
11868 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11869 data.GetParameter()->Reset();
11870 data.SetSecondPassCallback(DisposeAndForceGcCallback2);
11874 THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
11875 LocalContext context;
11876 v8::Isolate* isolate = context->GetIsolate();
11878 v8::Persistent<v8::Object> handle1, handle2;
11880 v8::HandleScope scope(isolate);
11881 handle1.Reset(isolate, v8::Object::New(isolate));
11882 handle2.Reset(isolate, v8::Object::New(isolate));
11884 handle1.SetWeak(&handle1, DisposeAndForceGcCallback1,
11885 v8::WeakCallbackType::kParameter);
11886 to_be_disposed.Reset(isolate, handle2);
11887 CcTest::heap()->CollectAllGarbage();
11890 void DisposingCallback(
11891 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11892 data.GetParameter()->Reset();
11895 void HandleCreatingCallback2(
11896 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11897 v8::HandleScope scope(data.GetIsolate());
11898 v8::Global<v8::Object>(data.GetIsolate(), v8::Object::New(data.GetIsolate()));
11902 void HandleCreatingCallback1(
11903 const v8::WeakCallbackInfo<v8::Persistent<v8::Object>>& data) {
11904 data.GetParameter()->Reset();
11905 data.SetSecondPassCallback(HandleCreatingCallback2);
11909 THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
11910 v8::Locker locker(CcTest::isolate());
11911 LocalContext context;
11912 v8::Isolate* isolate = context->GetIsolate();
11914 v8::Persistent<v8::Object> handle1, handle2, handle3;
11916 v8::HandleScope scope(isolate);
11917 handle3.Reset(isolate, v8::Object::New(isolate));
11918 handle2.Reset(isolate, v8::Object::New(isolate));
11919 handle1.Reset(isolate, v8::Object::New(isolate));
11921 handle2.SetWeak(&handle2, DisposingCallback,
11922 v8::WeakCallbackType::kParameter);
11923 handle3.SetWeak(&handle3, HandleCreatingCallback1,
11924 v8::WeakCallbackType::kParameter);
11925 CcTest::heap()->CollectAllGarbage();
11926 EmptyMessageQueues(isolate);
11930 THREADED_TEST(CheckForCrossContextObjectLiterals) {
11931 v8::V8::Initialize();
11934 const char* sources[nof] = {
11935 "try { [ 2, 3, 4 ].forEach(5); } catch(e) { e.toString(); }",
11939 for (int i = 0; i < nof; i++) {
11940 const char* source = sources[i];
11941 { v8::HandleScope scope(CcTest::isolate());
11942 LocalContext context;
11943 CompileRun(source);
11945 { v8::HandleScope scope(CcTest::isolate());
11946 LocalContext context;
11947 CompileRun(source);
11953 static v8::Handle<Value> NestedScope(v8::Local<Context> env) {
11954 v8::EscapableHandleScope inner(env->GetIsolate());
11956 v8::Local<Value> three = v8_num(3);
11957 v8::Local<Value> value = inner.Escape(three);
11963 THREADED_TEST(NestedHandleScopeAndContexts) {
11964 v8::Isolate* isolate = CcTest::isolate();
11965 v8::HandleScope outer(isolate);
11966 v8::Local<Context> env = Context::New(isolate);
11968 v8::Handle<Value> value = NestedScope(env);
11969 v8::Handle<String> str(value->ToString(isolate));
11970 CHECK(!str.IsEmpty());
11975 static bool MatchPointers(void* key1, void* key2) {
11976 return key1 == key2;
11980 struct SymbolInfo {
11987 class SetFunctionEntryHookTest {
11989 SetFunctionEntryHookTest() {
11990 CHECK(instance_ == NULL);
11993 ~SetFunctionEntryHookTest() {
11994 CHECK(instance_ == this);
11999 symbol_locations_.clear();
12000 invocations_.clear();
12003 void OnJitEvent(const v8::JitCodeEvent* event);
12004 static void JitEvent(const v8::JitCodeEvent* event) {
12005 CHECK(instance_ != NULL);
12006 instance_->OnJitEvent(event);
12009 void OnEntryHook(uintptr_t function,
12010 uintptr_t return_addr_location);
12011 static void EntryHook(uintptr_t function,
12012 uintptr_t return_addr_location) {
12013 CHECK(instance_ != NULL);
12014 instance_->OnEntryHook(function, return_addr_location);
12017 static void RuntimeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
12018 CHECK(instance_ != NULL);
12019 args.GetReturnValue().Set(v8_num(42));
12021 void RunLoopInNewEnv(v8::Isolate* isolate);
12023 // Records addr as location of symbol.
12024 void InsertSymbolAt(i::Address addr, SymbolInfo* symbol);
12026 // Finds the symbol containing addr
12027 SymbolInfo* FindSymbolForAddr(i::Address addr);
12028 // Returns the number of invocations where the caller name contains
12029 // \p caller_name and the function name contains \p function_name.
12030 int CountInvocations(const char* caller_name,
12031 const char* function_name);
12033 i::Handle<i::JSFunction> foo_func_;
12034 i::Handle<i::JSFunction> bar_func_;
12036 typedef std::map<size_t, SymbolInfo> SymbolMap;
12037 typedef std::map<i::Address, SymbolInfo*> SymbolLocationMap;
12038 typedef std::map<std::pair<SymbolInfo*, SymbolInfo*>, int> InvocationMap;
12039 SymbolMap symbols_;
12040 SymbolLocationMap symbol_locations_;
12041 InvocationMap invocations_;
12043 static SetFunctionEntryHookTest* instance_;
12045 SetFunctionEntryHookTest* SetFunctionEntryHookTest::instance_ = NULL;
12048 // Returns true if addr is in the range [start, start+len).
12049 static bool Overlaps(i::Address start, size_t len, i::Address addr) {
12050 if (start <= addr && start + len > addr)
12056 void SetFunctionEntryHookTest::InsertSymbolAt(i::Address addr,
12057 SymbolInfo* symbol) {
12058 // Insert the symbol at the new location.
12059 SymbolLocationMap::iterator it =
12060 symbol_locations_.insert(std::make_pair(addr, symbol)).first;
12061 // Now erase symbols to the left and right that overlap this one.
12062 while (it != symbol_locations_.begin()) {
12063 SymbolLocationMap::iterator left = it;
12065 if (!Overlaps(left->first, left->second->size, addr))
12067 symbol_locations_.erase(left);
12070 // Now erase symbols to the left and right that overlap this one.
12072 SymbolLocationMap::iterator right = it;
12074 if (right == symbol_locations_.end())
12076 if (!Overlaps(addr, symbol->size, right->first))
12078 symbol_locations_.erase(right);
12083 void SetFunctionEntryHookTest::OnJitEvent(const v8::JitCodeEvent* event) {
12084 switch (event->type) {
12085 case v8::JitCodeEvent::CODE_ADDED: {
12086 CHECK(event->code_start != NULL);
12087 CHECK_NE(0, static_cast<int>(event->code_len));
12088 CHECK(event->name.str != NULL);
12089 size_t symbol_id = symbols_.size();
12091 // Record the new symbol.
12092 SymbolInfo& info = symbols_[symbol_id];
12093 info.id = symbol_id;
12094 info.size = event->code_len;
12095 info.name.assign(event->name.str, event->name.str + event->name.len);
12097 // And record it's location.
12098 InsertSymbolAt(reinterpret_cast<i::Address>(event->code_start), &info);
12102 case v8::JitCodeEvent::CODE_MOVED: {
12103 // We would like to never see code move that we haven't seen before,
12104 // but the code creation event does not happen until the line endings
12105 // have been calculated (this is so that we can report the line in the
12106 // script at which the function source is found, see
12107 // Compiler::RecordFunctionCompilation) and the line endings
12108 // calculations can cause a GC, which can move the newly created code
12109 // before its existence can be logged.
12110 SymbolLocationMap::iterator it(
12111 symbol_locations_.find(
12112 reinterpret_cast<i::Address>(event->code_start)));
12113 if (it != symbol_locations_.end()) {
12114 // Found a symbol at this location, move it.
12115 SymbolInfo* info = it->second;
12116 symbol_locations_.erase(it);
12117 InsertSymbolAt(reinterpret_cast<i::Address>(event->new_code_start),
12126 void SetFunctionEntryHookTest::OnEntryHook(
12127 uintptr_t function, uintptr_t return_addr_location) {
12128 // Get the function's code object.
12129 i::Code* function_code = i::Code::GetCodeFromTargetAddress(
12130 reinterpret_cast<i::Address>(function));
12131 CHECK(function_code != NULL);
12133 // Then try and look up the caller's code object.
12134 i::Address caller = *reinterpret_cast<i::Address*>(return_addr_location);
12136 // Count the invocation.
12137 SymbolInfo* caller_symbol = FindSymbolForAddr(caller);
12138 SymbolInfo* function_symbol =
12139 FindSymbolForAddr(reinterpret_cast<i::Address>(function));
12140 ++invocations_[std::make_pair(caller_symbol, function_symbol)];
12142 if (!bar_func_.is_null() && function_code == bar_func_->code()) {
12143 // Check that we have a symbol for the "bar" function at the right location.
12144 SymbolLocationMap::iterator it(
12145 symbol_locations_.find(function_code->instruction_start()));
12146 CHECK(it != symbol_locations_.end());
12149 if (!foo_func_.is_null() && function_code == foo_func_->code()) {
12150 // Check that we have a symbol for "foo" at the right location.
12151 SymbolLocationMap::iterator it(
12152 symbol_locations_.find(function_code->instruction_start()));
12153 CHECK(it != symbol_locations_.end());
12158 SymbolInfo* SetFunctionEntryHookTest::FindSymbolForAddr(i::Address addr) {
12159 SymbolLocationMap::iterator it(symbol_locations_.lower_bound(addr));
12160 // Do we have a direct hit on a symbol?
12161 if (it != symbol_locations_.end()) {
12162 if (it->first == addr)
12166 // If not a direct hit, it'll have to be the previous symbol.
12167 if (it == symbol_locations_.begin())
12171 size_t offs = addr - it->first;
12172 if (offs < it->second->size)
12179 int SetFunctionEntryHookTest::CountInvocations(
12180 const char* caller_name, const char* function_name) {
12181 InvocationMap::iterator it(invocations_.begin());
12182 int invocations = 0;
12183 for (; it != invocations_.end(); ++it) {
12184 SymbolInfo* caller = it->first.first;
12185 SymbolInfo* function = it->first.second;
12187 // Filter out non-matching functions.
12188 if (function_name != NULL) {
12189 if (function->name.find(function_name) == std::string::npos)
12193 // Filter out non-matching callers.
12194 if (caller_name != NULL) {
12195 if (caller == NULL)
12197 if (caller->name.find(caller_name) == std::string::npos)
12201 // It matches add the invocation count to the tally.
12202 invocations += it->second;
12205 return invocations;
12209 void SetFunctionEntryHookTest::RunLoopInNewEnv(v8::Isolate* isolate) {
12210 v8::HandleScope outer(isolate);
12211 v8::Local<Context> env = Context::New(isolate);
12214 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12215 t->Set(v8_str("asdf"), v8::FunctionTemplate::New(isolate, RuntimeCallback));
12216 env->Global()->Set(v8_str("obj"), t->NewInstance());
12218 const char* script =
12219 "function bar() {\n"
12221 " for (i = 0; i < 100; ++i)\n"
12225 "function foo(i) { return i * i; }\n"
12226 "// Invoke on the runtime function.\n"
12228 CompileRun(script);
12229 bar_func_ = i::Handle<i::JSFunction>::cast(
12230 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))));
12231 DCHECK(!bar_func_.is_null());
12234 i::Handle<i::JSFunction>::cast(
12235 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))));
12236 DCHECK(!foo_func_.is_null());
12238 v8::Handle<v8::Value> value = CompileRun("bar();");
12239 CHECK(value->IsNumber());
12240 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12242 // Test the optimized codegen path.
12243 value = CompileRun("%OptimizeFunctionOnNextCall(foo);"
12245 CHECK(value->IsNumber());
12246 CHECK_EQ(9801.0, v8::Number::Cast(*value)->Value());
12252 void SetFunctionEntryHookTest::RunTest() {
12253 // Work in a new isolate throughout.
12254 v8::Isolate::CreateParams create_params;
12255 create_params.entry_hook = EntryHook;
12256 create_params.code_event_handler = JitEvent;
12257 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12258 v8::Isolate* isolate = v8::Isolate::New(create_params);
12261 v8::Isolate::Scope scope(isolate);
12263 RunLoopInNewEnv(isolate);
12265 // Check the exepected invocation counts.
12266 CHECK_EQ(2, CountInvocations(NULL, "bar"));
12267 CHECK_EQ(200, CountInvocations("bar", "foo"));
12268 CHECK_EQ(200, CountInvocations(NULL, "foo"));
12270 // Verify that we have an entry hook on some specific stubs.
12271 CHECK_NE(0, CountInvocations(NULL, "CEntryStub"));
12272 CHECK_NE(0, CountInvocations(NULL, "JSEntryStub"));
12273 CHECK_NE(0, CountInvocations(NULL, "JSEntryTrampoline"));
12275 isolate->Dispose();
12279 // Make sure a second isolate is unaffected by the previous entry hook.
12280 create_params = v8::Isolate::CreateParams();
12281 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12282 isolate = v8::Isolate::New(create_params);
12284 v8::Isolate::Scope scope(isolate);
12286 // Reset the entry count to zero and set the entry hook.
12287 RunLoopInNewEnv(isolate);
12289 // We should record no invocations in this isolate.
12290 CHECK_EQ(0, static_cast<int>(invocations_.size()));
12293 isolate->Dispose();
12297 TEST(SetFunctionEntryHook) {
12298 // FunctionEntryHook does not work well with experimental natives.
12299 // Experimental natives are compiled during snapshot deserialization.
12300 // This test breaks because InstallGetter (function from snapshot that
12301 // only gets called from experimental natives) is compiled with entry hooks.
12302 i::FLAG_allow_natives_syntax = true;
12303 i::FLAG_use_inlining = false;
12305 SetFunctionEntryHookTest test;
12310 static i::HashMap* code_map = NULL;
12311 static i::HashMap* jitcode_line_info = NULL;
12312 static int saw_bar = 0;
12313 static int move_events = 0;
12316 static bool FunctionNameIs(const char* expected,
12317 const v8::JitCodeEvent* event) {
12318 // Log lines for functions are of the general form:
12319 // "LazyCompile:<type><function_name>", where the type is one of
12321 static const char kPreamble[] = "LazyCompile:";
12322 static size_t kPreambleLen = sizeof(kPreamble) - 1;
12324 if (event->name.len < sizeof(kPreamble) - 1 ||
12325 strncmp(kPreamble, event->name.str, kPreambleLen) != 0) {
12329 const char* tail = event->name.str + kPreambleLen;
12330 size_t tail_len = event->name.len - kPreambleLen;
12331 size_t expected_len = strlen(expected);
12332 if (tail_len > 1 && (*tail == '*' || *tail == '~')) {
12337 // Check for tails like 'bar :1'.
12338 if (tail_len > expected_len + 2 &&
12339 tail[expected_len] == ' ' &&
12340 tail[expected_len + 1] == ':' &&
12341 tail[expected_len + 2] &&
12342 !strncmp(tail, expected, expected_len)) {
12346 if (tail_len != expected_len)
12349 return strncmp(tail, expected, expected_len) == 0;
12353 static void event_handler(const v8::JitCodeEvent* event) {
12354 CHECK(event != NULL);
12355 CHECK(code_map != NULL);
12356 CHECK(jitcode_line_info != NULL);
12358 class DummyJitCodeLineInfo {
12361 switch (event->type) {
12362 case v8::JitCodeEvent::CODE_ADDED: {
12363 CHECK(event->code_start != NULL);
12364 CHECK_NE(0, static_cast<int>(event->code_len));
12365 CHECK(event->name.str != NULL);
12366 i::HashMap::Entry* entry = code_map->LookupOrInsert(
12367 event->code_start, i::ComputePointerHash(event->code_start));
12368 entry->value = reinterpret_cast<void*>(event->code_len);
12370 if (FunctionNameIs("bar", event)) {
12376 case v8::JitCodeEvent::CODE_MOVED: {
12377 uint32_t hash = i::ComputePointerHash(event->code_start);
12378 // We would like to never see code move that we haven't seen before,
12379 // but the code creation event does not happen until the line endings
12380 // have been calculated (this is so that we can report the line in the
12381 // script at which the function source is found, see
12382 // Compiler::RecordFunctionCompilation) and the line endings
12383 // calculations can cause a GC, which can move the newly created code
12384 // before its existence can be logged.
12385 i::HashMap::Entry* entry = code_map->Lookup(event->code_start, hash);
12386 if (entry != NULL) {
12389 CHECK_EQ(reinterpret_cast<void*>(event->code_len), entry->value);
12390 code_map->Remove(event->code_start, hash);
12392 entry = code_map->LookupOrInsert(
12393 event->new_code_start,
12394 i::ComputePointerHash(event->new_code_start));
12395 entry->value = reinterpret_cast<void*>(event->code_len);
12400 case v8::JitCodeEvent::CODE_REMOVED:
12401 // Object/code removal events are currently not dispatched from the GC.
12405 // For CODE_START_LINE_INFO_RECORDING event, we will create one
12406 // DummyJitCodeLineInfo data structure pointed by event->user_dat. We
12407 // record it in jitcode_line_info.
12408 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: {
12409 DummyJitCodeLineInfo* line_info = new DummyJitCodeLineInfo();
12410 v8::JitCodeEvent* temp_event = const_cast<v8::JitCodeEvent*>(event);
12411 temp_event->user_data = line_info;
12412 i::HashMap::Entry* entry = jitcode_line_info->LookupOrInsert(
12413 line_info, i::ComputePointerHash(line_info));
12414 entry->value = reinterpret_cast<void*>(line_info);
12417 // For these two events, we will check whether the event->user_data
12418 // data structure is created before during CODE_START_LINE_INFO_RECORDING
12419 // event. And delete it in CODE_END_LINE_INFO_RECORDING event handling.
12420 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: {
12421 CHECK(event->user_data != NULL);
12422 uint32_t hash = i::ComputePointerHash(event->user_data);
12423 i::HashMap::Entry* entry =
12424 jitcode_line_info->Lookup(event->user_data, hash);
12425 CHECK(entry != NULL);
12426 delete reinterpret_cast<DummyJitCodeLineInfo*>(event->user_data);
12430 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: {
12431 CHECK(event->user_data != NULL);
12432 uint32_t hash = i::ComputePointerHash(event->user_data);
12433 i::HashMap::Entry* entry =
12434 jitcode_line_info->Lookup(event->user_data, hash);
12435 CHECK(entry != NULL);
12440 // Impossible event.
12447 UNINITIALIZED_TEST(SetJitCodeEventHandler) {
12448 i::FLAG_stress_compaction = true;
12449 i::FLAG_incremental_marking = false;
12450 if (i::FLAG_never_compact) return;
12451 const char* script =
12454 " for (i = 0; i < 10; ++i)"
12458 "function foo(i) { return i; };"
12461 // Run this test in a new isolate to make sure we don't
12462 // have remnants of state from other code.
12463 v8::Isolate::CreateParams create_params;
12464 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
12465 v8::Isolate* isolate = v8::Isolate::New(create_params);
12467 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
12468 i::Heap* heap = i_isolate->heap();
12470 // Start with a clean slate.
12471 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Prepare");
12474 v8::HandleScope scope(isolate);
12475 i::HashMap code(MatchPointers);
12478 i::HashMap lineinfo(MatchPointers);
12479 jitcode_line_info = &lineinfo;
12484 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, event_handler);
12486 // Generate new code objects sparsely distributed across several
12487 // different fragmented code-space pages.
12488 const int kIterations = 10;
12489 for (int i = 0; i < kIterations; ++i) {
12490 LocalContext env(isolate);
12491 i::AlwaysAllocateScope always_allocate(i_isolate);
12492 SimulateFullSpace(heap->code_space());
12493 CompileRun(script);
12495 // Keep a strong reference to the code object in the handle scope.
12496 i::Handle<i::Code> bar_code(i::Handle<i::JSFunction>::cast(
12497 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("bar"))))->code());
12498 i::Handle<i::Code> foo_code(i::Handle<i::JSFunction>::cast(
12499 v8::Utils::OpenHandle(*env->Global()->Get(v8_str("foo"))))->code());
12501 // Clear the compilation cache to get more wastage.
12502 reinterpret_cast<i::Isolate*>(isolate)->compilation_cache()->Clear();
12505 // Force code movement.
12506 heap->CollectAllAvailableGarbage("TestSetJitCodeEventHandler_Move");
12508 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12510 CHECK_LE(kIterations, saw_bar);
12511 CHECK_LT(0, move_events);
12514 jitcode_line_info = NULL;
12518 isolate->Dispose();
12520 // Do this in a new isolate.
12521 isolate = v8::Isolate::New(create_params);
12524 // Verify that we get callbacks for existing code objects when we
12525 // request enumeration of existing code.
12527 v8::HandleScope scope(isolate);
12528 LocalContext env(isolate);
12529 CompileRun(script);
12531 // Now get code through initial iteration.
12532 i::HashMap code(MatchPointers);
12535 i::HashMap lineinfo(MatchPointers);
12536 jitcode_line_info = &lineinfo;
12538 isolate->SetJitCodeEventHandler(v8::kJitCodeEventEnumExisting,
12540 isolate->SetJitCodeEventHandler(v8::kJitCodeEventDefault, NULL);
12542 jitcode_line_info = NULL;
12543 // We expect that we got some events. Note that if we could get code removal
12544 // notifications, we could compare two collections, one created by listening
12545 // from the time of creation of an isolate, and the other by subscribing
12546 // with EnumExisting.
12547 CHECK_LT(0u, code.occupancy());
12553 isolate->Dispose();
12557 THREADED_TEST(ExternalAllocatedMemory) {
12558 v8::Isolate* isolate = CcTest::isolate();
12559 v8::HandleScope outer(isolate);
12560 v8::Local<Context> env(Context::New(isolate));
12561 CHECK(!env.IsEmpty());
12562 const int64_t kSize = 1024*1024;
12563 int64_t baseline = isolate->AdjustAmountOfExternalAllocatedMemory(0);
12564 CHECK_EQ(baseline + kSize,
12565 isolate->AdjustAmountOfExternalAllocatedMemory(kSize));
12567 isolate->AdjustAmountOfExternalAllocatedMemory(-kSize));
12568 const int64_t kTriggerGCSize =
12569 v8::internal::Internals::kExternalAllocationLimit + 1;
12570 CHECK_EQ(baseline + kTriggerGCSize,
12571 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize));
12573 isolate->AdjustAmountOfExternalAllocatedMemory(-kTriggerGCSize));
12577 TEST(Regress51719) {
12578 i::FLAG_incremental_marking = false;
12579 CcTest::InitializeVM();
12581 const int64_t kTriggerGCSize =
12582 v8::internal::Internals::kExternalAllocationLimit + 1;
12583 v8::Isolate* isolate = CcTest::isolate();
12584 isolate->AdjustAmountOfExternalAllocatedMemory(kTriggerGCSize);
12588 // Regression test for issue 54, object templates with internal fields
12589 // but no accessors or interceptors did not get their internal field
12590 // count set on instances.
12591 THREADED_TEST(Regress54) {
12592 LocalContext context;
12593 v8::Isolate* isolate = context->GetIsolate();
12594 v8::HandleScope outer(isolate);
12595 static v8::Persistent<v8::ObjectTemplate> templ;
12596 if (templ.IsEmpty()) {
12597 v8::EscapableHandleScope inner(isolate);
12598 v8::Local<v8::ObjectTemplate> local = v8::ObjectTemplate::New(isolate);
12599 local->SetInternalFieldCount(1);
12600 templ.Reset(isolate, inner.Escape(local));
12602 v8::Handle<v8::Object> result =
12603 v8::Local<v8::ObjectTemplate>::New(isolate, templ)->NewInstance();
12604 CHECK_EQ(1, result->InternalFieldCount());
12608 // If part of the threaded tests, this test makes ThreadingTest fail
12610 TEST(CatchStackOverflow) {
12611 LocalContext context;
12612 v8::HandleScope scope(context->GetIsolate());
12613 v8::TryCatch try_catch(context->GetIsolate());
12614 v8::Handle<v8::Value> result = CompileRun(
12620 CHECK(result.IsEmpty());
12624 static void CheckTryCatchSourceInfo(v8::Handle<v8::Script> script,
12625 const char* resource_name,
12627 v8::HandleScope scope(CcTest::isolate());
12628 v8::TryCatch try_catch(CcTest::isolate());
12629 v8::Handle<v8::Value> result = script->Run();
12630 CHECK(result.IsEmpty());
12631 CHECK(try_catch.HasCaught());
12632 v8::Handle<v8::Message> message = try_catch.Message();
12633 CHECK(!message.IsEmpty());
12634 CHECK_EQ(10 + line_offset, message->GetLineNumber());
12635 CHECK_EQ(91, message->GetStartPosition());
12636 CHECK_EQ(92, message->GetEndPosition());
12637 CHECK_EQ(2, message->GetStartColumn());
12638 CHECK_EQ(3, message->GetEndColumn());
12639 v8::String::Utf8Value line(message->GetSourceLine());
12640 CHECK_EQ(0, strcmp(" throw 'nirk';", *line));
12641 v8::String::Utf8Value name(message->GetScriptOrigin().ResourceName());
12642 CHECK_EQ(0, strcmp(resource_name, *name));
12646 THREADED_TEST(TryCatchSourceInfo) {
12647 LocalContext context;
12648 v8::HandleScope scope(context->GetIsolate());
12649 v8::Local<v8::String> source = v8_str(
12650 "function Foo() {\n"
12654 "function Bar() {\n"
12658 "function Baz() {\n"
12664 const char* resource_name;
12665 v8::Handle<v8::Script> script;
12666 resource_name = "test.js";
12667 script = CompileWithOrigin(source, resource_name);
12668 CheckTryCatchSourceInfo(script, resource_name, 0);
12670 resource_name = "test1.js";
12671 v8::ScriptOrigin origin1(
12672 v8::String::NewFromUtf8(context->GetIsolate(), resource_name));
12673 script = v8::Script::Compile(source, &origin1);
12674 CheckTryCatchSourceInfo(script, resource_name, 0);
12676 resource_name = "test2.js";
12677 v8::ScriptOrigin origin2(
12678 v8::String::NewFromUtf8(context->GetIsolate(), resource_name),
12679 v8::Integer::New(context->GetIsolate(), 7));
12680 script = v8::Script::Compile(source, &origin2);
12681 CheckTryCatchSourceInfo(script, resource_name, 7);
12685 THREADED_TEST(TryCatchSourceInfoForEOSError) {
12686 LocalContext context;
12687 v8::HandleScope scope(context->GetIsolate());
12688 v8::TryCatch try_catch(context->GetIsolate());
12689 v8::Script::Compile(v8_str("!\n"));
12690 CHECK(try_catch.HasCaught());
12691 v8::Handle<v8::Message> message = try_catch.Message();
12692 CHECK_EQ(1, message->GetLineNumber());
12693 CHECK_EQ(0, message->GetStartColumn());
12697 THREADED_TEST(CompilationCache) {
12698 LocalContext context;
12699 v8::HandleScope scope(context->GetIsolate());
12700 v8::Handle<v8::String> source0 =
12701 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12702 v8::Handle<v8::String> source1 =
12703 v8::String::NewFromUtf8(context->GetIsolate(), "1234");
12704 v8::Handle<v8::Script> script0 = CompileWithOrigin(source0, "test.js");
12705 v8::Handle<v8::Script> script1 = CompileWithOrigin(source1, "test.js");
12706 v8::Handle<v8::Script> script2 =
12707 v8::Script::Compile(source0); // different origin
12708 CHECK_EQ(1234, script0->Run()->Int32Value());
12709 CHECK_EQ(1234, script1->Run()->Int32Value());
12710 CHECK_EQ(1234, script2->Run()->Int32Value());
12714 static void FunctionNameCallback(
12715 const v8::FunctionCallbackInfo<v8::Value>& args) {
12716 ApiTestFuzzer::Fuzz();
12717 args.GetReturnValue().Set(v8_num(42));
12721 THREADED_TEST(CallbackFunctionName) {
12722 LocalContext context;
12723 v8::Isolate* isolate = context->GetIsolate();
12724 v8::HandleScope scope(isolate);
12725 Local<ObjectTemplate> t = ObjectTemplate::New(isolate);
12726 t->Set(v8_str("asdf"),
12727 v8::FunctionTemplate::New(isolate, FunctionNameCallback));
12728 context->Global()->Set(v8_str("obj"), t->NewInstance());
12729 v8::Handle<v8::Value> value = CompileRun("obj.asdf.name");
12730 CHECK(value->IsString());
12731 v8::String::Utf8Value name(value);
12732 CHECK_EQ(0, strcmp("asdf", *name));
12736 THREADED_TEST(DateAccess) {
12737 LocalContext context;
12738 v8::HandleScope scope(context->GetIsolate());
12739 v8::Handle<v8::Value> date =
12740 v8::Date::New(context->GetIsolate(), 1224744689038.0);
12741 CHECK(date->IsDate());
12742 CHECK_EQ(1224744689038.0, date.As<v8::Date>()->ValueOf());
12746 void CheckProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12747 unsigned elmc, const char* elmv[]) {
12748 v8::Handle<v8::Object> obj = val.As<v8::Object>();
12749 v8::Handle<v8::Array> props = obj->GetPropertyNames();
12750 CHECK_EQ(elmc, props->Length());
12751 for (unsigned i = 0; i < elmc; i++) {
12752 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12753 CHECK_EQ(0, strcmp(elmv[i], *elm));
12758 void CheckOwnProperties(v8::Isolate* isolate, v8::Handle<v8::Value> val,
12759 unsigned elmc, const char* elmv[]) {
12760 v8::Handle<v8::Object> obj = val.As<v8::Object>();
12761 v8::Handle<v8::Array> props = obj->GetOwnPropertyNames();
12762 CHECK_EQ(elmc, props->Length());
12763 for (unsigned i = 0; i < elmc; i++) {
12764 v8::String::Utf8Value elm(props->Get(v8::Integer::New(isolate, i)));
12765 CHECK_EQ(0, strcmp(elmv[i], *elm));
12770 THREADED_TEST(PropertyEnumeration) {
12771 LocalContext context;
12772 v8::Isolate* isolate = context->GetIsolate();
12773 v8::HandleScope scope(isolate);
12774 v8::Handle<v8::Value> obj = CompileRun(
12777 "result[1] = {a: 1, b: 2};"
12778 "result[2] = [1, 2, 3];"
12779 "var proto = {x: 1, y: 2, z: 3};"
12780 "var x = { __proto__: proto, w: 0, z: 1 };"
12783 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12784 CHECK_EQ(4u, elms->Length());
12786 const char** elmv0 = NULL;
12788 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12789 CheckOwnProperties(
12790 isolate, elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12792 const char* elmv1[] = {"a", "b"};
12794 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12795 CheckOwnProperties(
12796 isolate, elms->Get(v8::Integer::New(isolate, 1)), elmc1, elmv1);
12798 const char* elmv2[] = {"0", "1", "2"};
12800 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12801 CheckOwnProperties(
12802 isolate, elms->Get(v8::Integer::New(isolate, 2)), elmc2, elmv2);
12804 const char* elmv3[] = {"w", "z", "x", "y"};
12806 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc3, elmv3);
12808 const char* elmv4[] = {"w", "z"};
12809 CheckOwnProperties(
12810 isolate, elms->Get(v8::Integer::New(isolate, 3)), elmc4, elmv4);
12814 THREADED_TEST(PropertyEnumeration2) {
12815 LocalContext context;
12816 v8::Isolate* isolate = context->GetIsolate();
12817 v8::HandleScope scope(isolate);
12818 v8::Handle<v8::Value> obj = CompileRun(
12821 "result[1] = {a: 1, b: 2};"
12822 "result[2] = [1, 2, 3];"
12823 "var proto = {x: 1, y: 2, z: 3};"
12824 "var x = { __proto__: proto, w: 0, z: 1 };"
12827 v8::Handle<v8::Array> elms = obj.As<v8::Array>();
12828 CHECK_EQ(4u, elms->Length());
12830 const char** elmv0 = NULL;
12831 CheckProperties(isolate,
12832 elms->Get(v8::Integer::New(isolate, 0)), elmc0, elmv0);
12834 v8::Handle<v8::Value> val = elms->Get(v8::Integer::New(isolate, 0));
12835 v8::Handle<v8::Array> props = val.As<v8::Object>()->GetPropertyNames();
12836 CHECK_EQ(0u, props->Length());
12837 for (uint32_t i = 0; i < props->Length(); i++) {
12838 printf("p[%u]\n", i);
12843 THREADED_TEST(AccessChecksReenabledCorrectly) {
12844 LocalContext context;
12845 v8::Isolate* isolate = context->GetIsolate();
12846 v8::HandleScope scope(isolate);
12847 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
12848 templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
12849 templ->Set(v8_str("a"), v8_str("a"));
12850 // Add more than 8 (see kMaxFastProperties) properties
12851 // so that the constructor will force copying map.
12852 // Cannot sprintf, gcc complains unsafety.
12854 for (char i = '0'; i <= '9' ; i++) {
12856 for (char j = '0'; j <= '9'; j++) {
12858 for (char k = '0'; k <= '9'; k++) {
12861 templ->Set(v8_str(buf), v8::Number::New(isolate, k));
12866 Local<v8::Object> instance_1 = templ->NewInstance();
12867 context->Global()->Set(v8_str("obj_1"), instance_1);
12869 Local<Value> value_1 = CompileRun("obj_1.a");
12870 CHECK(value_1.IsEmpty());
12872 Local<v8::Object> instance_2 = templ->NewInstance();
12873 context->Global()->Set(v8_str("obj_2"), instance_2);
12875 Local<Value> value_2 = CompileRun("obj_2.a");
12876 CHECK(value_2.IsEmpty());
12880 // Tests that ScriptData can be serialized and deserialized.
12881 TEST(PreCompileSerialization) {
12882 v8::V8::Initialize();
12884 v8::Isolate* isolate = env->GetIsolate();
12885 HandleScope handle_scope(isolate);
12887 i::FLAG_min_preparse_length = 0;
12888 const char* script = "function foo(a) { return a+1; }";
12889 v8::ScriptCompiler::Source source(v8_str(script));
12890 v8::ScriptCompiler::Compile(isolate, &source,
12891 v8::ScriptCompiler::kProduceParserCache);
12893 const v8::ScriptCompiler::CachedData* cd = source.GetCachedData();
12894 i::byte* serialized_data = i::NewArray<i::byte>(cd->length);
12895 i::MemCopy(serialized_data, cd->data, cd->length);
12898 i::ScriptData* deserialized = new i::ScriptData(serialized_data, cd->length);
12900 // Verify that the original is the same as the deserialized.
12901 CHECK_EQ(cd->length, deserialized->length());
12902 CHECK_EQ(0, memcmp(cd->data, deserialized->data(), cd->length));
12904 delete deserialized;
12905 i::DeleteArray(serialized_data);
12909 // This tests that we do not allow dictionary load/call inline caches
12910 // to use functions that have not yet been compiled. The potential
12911 // problem of loading a function that has not yet been compiled can
12912 // arise because we share code between contexts via the compilation
12914 THREADED_TEST(DictionaryICLoadedFunction) {
12915 v8::HandleScope scope(CcTest::isolate());
12917 for (int i = 0; i < 2; i++) {
12918 LocalContext context;
12919 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
12920 context->Global()->Delete(v8_str("tmp"));
12921 CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
12924 for (int i = 0; i < 2; i++) {
12925 LocalContext context;
12926 context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
12927 context->Global()->Delete(v8_str("tmp"));
12928 CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
12933 // Test that cross-context new calls use the context of the callee to
12934 // create the new JavaScript object.
12935 THREADED_TEST(CrossContextNew) {
12936 v8::Isolate* isolate = CcTest::isolate();
12937 v8::HandleScope scope(isolate);
12938 v8::Local<Context> context0 = Context::New(isolate);
12939 v8::Local<Context> context1 = Context::New(isolate);
12941 // Allow cross-domain access.
12942 Local<String> token = v8_str("<security token>");
12943 context0->SetSecurityToken(token);
12944 context1->SetSecurityToken(token);
12946 // Set an 'x' property on the Object prototype and define a
12947 // constructor function in context0.
12949 CompileRun("Object.prototype.x = 42; function C() {};");
12952 // Call the constructor function from context0 and check that the
12953 // result has the 'x' property.
12955 context1->Global()->Set(v8_str("other"), context0->Global());
12956 Local<Value> value = CompileRun("var instance = new other.C(); instance.x");
12957 CHECK(value->IsInt32());
12958 CHECK_EQ(42, value->Int32Value());
12963 // Verify that we can clone an object
12964 TEST(ObjectClone) {
12966 v8::Isolate* isolate = env->GetIsolate();
12967 v8::HandleScope scope(isolate);
12969 const char* sample =
12971 "rv.alpha = 'hello';" \
12975 // Create an object, verify basics.
12976 Local<Value> val = CompileRun(sample);
12977 CHECK(val->IsObject());
12978 Local<v8::Object> obj = val.As<v8::Object>();
12979 obj->Set(v8_str("gamma"), v8_str("cloneme"));
12981 CHECK(v8_str("hello")->Equals(obj->Get(v8_str("alpha"))));
12982 CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
12983 CHECK(v8_str("cloneme")->Equals(obj->Get(v8_str("gamma"))));
12986 Local<v8::Object> clone = obj->Clone();
12987 CHECK(v8_str("hello")->Equals(clone->Get(v8_str("alpha"))));
12988 CHECK(v8::Integer::New(isolate, 123)->Equals(clone->Get(v8_str("beta"))));
12989 CHECK(v8_str("cloneme")->Equals(clone->Get(v8_str("gamma"))));
12991 // Set a property on the clone, verify each object.
12992 clone->Set(v8_str("beta"), v8::Integer::New(isolate, 456));
12993 CHECK(v8::Integer::New(isolate, 123)->Equals(obj->Get(v8_str("beta"))));
12994 CHECK(v8::Integer::New(isolate, 456)->Equals(clone->Get(v8_str("beta"))));
12998 class OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
13000 explicit OneByteVectorResource(i::Vector<const char> vector)
13002 virtual ~OneByteVectorResource() {}
13003 virtual size_t length() const { return data_.length(); }
13004 virtual const char* data() const { return data_.start(); }
13006 i::Vector<const char> data_;
13010 class UC16VectorResource : public v8::String::ExternalStringResource {
13012 explicit UC16VectorResource(i::Vector<const i::uc16> vector)
13014 virtual ~UC16VectorResource() {}
13015 virtual size_t length() const { return data_.length(); }
13016 virtual const i::uc16* data() const { return data_.start(); }
13018 i::Vector<const i::uc16> data_;
13022 static void MorphAString(i::String* string,
13023 OneByteVectorResource* one_byte_resource,
13024 UC16VectorResource* uc16_resource) {
13025 CHECK(i::StringShape(string).IsExternal());
13026 if (string->IsOneByteRepresentation()) {
13027 // Check old map is not internalized or long.
13028 CHECK(string->map() == CcTest::heap()->external_one_byte_string_map());
13029 // Morph external string to be TwoByte string.
13030 string->set_map(CcTest::heap()->external_string_map());
13031 i::ExternalTwoByteString* morphed =
13032 i::ExternalTwoByteString::cast(string);
13033 morphed->set_resource(uc16_resource);
13035 // Check old map is not internalized or long.
13036 CHECK(string->map() == CcTest::heap()->external_string_map());
13037 // Morph external string to be one-byte string.
13038 string->set_map(CcTest::heap()->external_one_byte_string_map());
13039 i::ExternalOneByteString* morphed = i::ExternalOneByteString::cast(string);
13040 morphed->set_resource(one_byte_resource);
13045 // Test that we can still flatten a string if the components it is built up
13046 // from have been turned into 16 bit strings in the mean time.
13047 THREADED_TEST(MorphCompositeStringTest) {
13048 char utf_buffer[129];
13049 const char* c_string = "Now is the time for all good men"
13050 " to come to the aid of the party";
13051 uint16_t* two_byte_string = AsciiToTwoByteString(c_string);
13054 i::Factory* factory = CcTest::i_isolate()->factory();
13055 v8::HandleScope scope(env->GetIsolate());
13056 OneByteVectorResource one_byte_resource(
13057 i::Vector<const char>(c_string, i::StrLength(c_string)));
13058 UC16VectorResource uc16_resource(
13059 i::Vector<const uint16_t>(two_byte_string,
13060 i::StrLength(c_string)));
13063 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13064 &one_byte_resource).ToHandleChecked()));
13066 v8::Utils::ToLocal(factory->NewExternalStringFromOneByte(
13067 &one_byte_resource).ToHandleChecked()));
13069 env->Global()->Set(v8_str("lhs"), lhs);
13070 env->Global()->Set(v8_str("rhs"), rhs);
13073 "var cons = lhs + rhs;"
13074 "var slice = lhs.substring(1, lhs.length - 1);"
13075 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);");
13077 CHECK(lhs->IsOneByte());
13078 CHECK(rhs->IsOneByte());
13080 MorphAString(*v8::Utils::OpenHandle(*lhs), &one_byte_resource,
13082 MorphAString(*v8::Utils::OpenHandle(*rhs), &one_byte_resource,
13085 // This should UTF-8 without flattening, since everything is ASCII.
13086 Handle<String> cons = v8_compile("cons")->Run().As<String>();
13087 CHECK_EQ(128, cons->Utf8Length());
13089 CHECK_EQ(129, cons->WriteUtf8(utf_buffer, -1, &nchars));
13090 CHECK_EQ(128, nchars);
13091 CHECK_EQ(0, strcmp(
13093 "Now is the time for all good men to come to the aid of the party"
13094 "Now is the time for all good men to come to the aid of the party"));
13096 // Now do some stuff to make sure the strings are flattened, etc.
13098 "/[^a-z]/.test(cons);"
13099 "/[^a-z]/.test(slice);"
13100 "/[^a-z]/.test(slice_on_cons);");
13101 const char* expected_cons =
13102 "Now is the time for all good men to come to the aid of the party"
13103 "Now is the time for all good men to come to the aid of the party";
13104 const char* expected_slice =
13105 "ow is the time for all good men to come to the aid of the part";
13106 const char* expected_slice_on_cons =
13107 "ow is the time for all good men to come to the aid of the party"
13108 "Now is the time for all good men to come to the aid of the part";
13109 CHECK(String::NewFromUtf8(env->GetIsolate(), expected_cons)
13110 ->Equals(env->Global()->Get(v8_str("cons"))));
13111 CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice)
13112 ->Equals(env->Global()->Get(v8_str("slice"))));
13113 CHECK(String::NewFromUtf8(env->GetIsolate(), expected_slice_on_cons)
13114 ->Equals(env->Global()->Get(v8_str("slice_on_cons"))));
13116 i::DeleteArray(two_byte_string);
13120 TEST(CompileExternalTwoByteSource) {
13121 LocalContext context;
13122 v8::HandleScope scope(context->GetIsolate());
13124 // This is a very short list of sources, which currently is to check for a
13125 // regression caused by r2703.
13126 const char* one_byte_sources[] = {
13128 "-0.5", // This mainly testes PushBack in the Scanner.
13129 "--0.5", // This mainly testes PushBack in the Scanner.
13132 // Compile the sources as external two byte strings.
13133 for (int i = 0; one_byte_sources[i] != NULL; i++) {
13134 uint16_t* two_byte_string = AsciiToTwoByteString(one_byte_sources[i]);
13135 TestResource* uc16_resource = new TestResource(two_byte_string);
13136 v8::Local<v8::String> source =
13137 v8::String::NewExternal(context->GetIsolate(), uc16_resource);
13138 v8::Script::Compile(source);
13143 #ifndef V8_INTERPRETED_REGEXP
13145 struct RegExpInterruptionData {
13146 v8::base::Atomic32 loop_count;
13147 UC16VectorResource* string_resource;
13148 v8::Persistent<v8::String> string;
13149 } regexp_interruption_data;
13152 class RegExpInterruptionThread : public v8::base::Thread {
13154 explicit RegExpInterruptionThread(v8::Isolate* isolate)
13155 : Thread(Options("TimeoutThread")), isolate_(isolate) {}
13157 virtual void Run() {
13158 for (v8::base::NoBarrier_Store(®exp_interruption_data.loop_count, 0);
13159 v8::base::NoBarrier_Load(®exp_interruption_data.loop_count) < 7;
13160 v8::base::NoBarrier_AtomicIncrement(
13161 ®exp_interruption_data.loop_count, 1)) {
13162 // Wait a bit before requesting GC.
13163 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
13164 reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
13166 // Wait a bit before terminating.
13167 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
13168 v8::V8::TerminateExecution(isolate_);
13172 v8::Isolate* isolate_;
13176 void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
13177 if (v8::base::NoBarrier_Load(®exp_interruption_data.loop_count) != 2) {
13180 v8::HandleScope scope(CcTest::isolate());
13181 v8::Local<v8::String> string = v8::Local<v8::String>::New(
13182 CcTest::isolate(), regexp_interruption_data.string);
13183 string->MakeExternal(regexp_interruption_data.string_resource);
13187 // Test that RegExp execution can be interrupted. Specifically, we test
13188 // * interrupting with GC
13189 // * turn the subject string from one-byte internal to two-byte external string
13190 // * force termination
13191 TEST(RegExpInterruption) {
13192 v8::HandleScope scope(CcTest::isolate());
13195 RegExpInterruptionThread timeout_thread(CcTest::isolate());
13197 v8::V8::AddGCPrologueCallback(RunBeforeGC);
13198 static const char* one_byte_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
13199 i::uc16* uc16_content = AsciiToTwoByteString(one_byte_content);
13200 v8::Local<v8::String> string = v8_str(one_byte_content);
13202 CcTest::global()->Set(v8_str("a"), string);
13203 regexp_interruption_data.string.Reset(CcTest::isolate(), string);
13204 regexp_interruption_data.string_resource = new UC16VectorResource(
13205 i::Vector<const i::uc16>(uc16_content, i::StrLength(one_byte_content)));
13207 v8::TryCatch try_catch(CcTest::isolate());
13208 timeout_thread.Start();
13210 CompileRun("/((a*)*)*b/.exec(a)");
13211 CHECK(try_catch.HasTerminated());
13213 timeout_thread.Join();
13215 regexp_interruption_data.string.Reset();
13216 i::DeleteArray(uc16_content);
13219 #endif // V8_INTERPRETED_REGEXP
13222 // Test that we cannot set a property on the global object if there
13223 // is a read-only property in the prototype chain.
13224 TEST(ReadOnlyPropertyInGlobalProto) {
13225 v8::Isolate* isolate = CcTest::isolate();
13226 v8::HandleScope scope(isolate);
13227 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13228 LocalContext context(0, templ);
13229 v8::Handle<v8::Object> global = context->Global();
13230 v8::Handle<v8::Object> global_proto =
13231 v8::Handle<v8::Object>::Cast(global->Get(v8_str("__proto__")));
13232 global_proto->ForceSet(v8_str("x"), v8::Integer::New(isolate, 0),
13234 global_proto->ForceSet(v8_str("y"), v8::Integer::New(isolate, 0),
13236 // Check without 'eval' or 'with'.
13237 v8::Handle<v8::Value> res =
13238 CompileRun("function f() { x = 42; return x; }; f()");
13239 CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13240 // Check with 'eval'.
13241 res = CompileRun("function f() { eval('1'); y = 43; return y; }; f()");
13242 CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13243 // Check with 'with'.
13244 res = CompileRun("function f() { with (this) { y = 44 }; return y; }; f()");
13245 CHECK(v8::Integer::New(isolate, 0)->Equals(res));
13248 static int force_set_set_count = 0;
13249 static int force_set_get_count = 0;
13250 bool pass_on_get = false;
13252 static void ForceSetGetter(v8::Local<v8::String> name,
13253 const v8::PropertyCallbackInfo<v8::Value>& info) {
13254 force_set_get_count++;
13258 info.GetReturnValue().Set(3);
13261 static void ForceSetSetter(v8::Local<v8::String> name,
13262 v8::Local<v8::Value> value,
13263 const v8::PropertyCallbackInfo<void>& info) {
13264 force_set_set_count++;
13267 static void ForceSetInterceptGetter(
13268 v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
13269 CHECK(name->IsString());
13270 ForceSetGetter(Local<String>::Cast(name), info);
13273 static void ForceSetInterceptSetter(
13274 v8::Local<v8::Name> name, v8::Local<v8::Value> value,
13275 const v8::PropertyCallbackInfo<v8::Value>& info) {
13276 force_set_set_count++;
13277 info.GetReturnValue().SetUndefined();
13282 force_set_get_count = 0;
13283 force_set_set_count = 0;
13284 pass_on_get = false;
13286 v8::Isolate* isolate = CcTest::isolate();
13287 v8::HandleScope scope(isolate);
13288 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13289 v8::Handle<v8::String> access_property =
13290 v8::String::NewFromUtf8(isolate, "a");
13291 templ->SetAccessor(access_property, ForceSetGetter, ForceSetSetter);
13292 LocalContext context(NULL, templ);
13293 v8::Handle<v8::Object> global = context->Global();
13295 // Ordinary properties
13296 v8::Handle<v8::String> simple_property =
13297 v8::String::NewFromUtf8(isolate, "p");
13298 global->ForceSet(simple_property, v8::Int32::New(isolate, 4), v8::ReadOnly);
13299 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13300 // This should fail because the property is read-only
13301 global->Set(simple_property, v8::Int32::New(isolate, 5));
13302 CHECK_EQ(4, global->Get(simple_property)->Int32Value());
13303 // This should succeed even though the property is read-only
13304 global->ForceSet(simple_property, v8::Int32::New(isolate, 6));
13305 CHECK_EQ(6, global->Get(simple_property)->Int32Value());
13308 CHECK_EQ(0, force_set_set_count);
13309 CHECK_EQ(0, force_set_get_count);
13310 CHECK_EQ(3, global->Get(access_property)->Int32Value());
13311 // CHECK_EQ the property shouldn't override it, just call the setter
13312 // which in this case does nothing.
13313 global->Set(access_property, v8::Int32::New(isolate, 7));
13314 CHECK_EQ(3, global->Get(access_property)->Int32Value());
13315 CHECK_EQ(1, force_set_set_count);
13316 CHECK_EQ(2, force_set_get_count);
13317 // ForceSet doesn't call the accessors for now.
13318 // TODO(verwaest): Update once blink doesn't rely on ForceSet to delete api
13320 global->ForceSet(access_property, v8::Int32::New(isolate, 8));
13321 CHECK_EQ(8, global->Get(access_property)->Int32Value());
13322 CHECK_EQ(1, force_set_set_count);
13323 CHECK_EQ(2, force_set_get_count);
13327 TEST(ForceSetWithInterceptor) {
13328 v8::Isolate* isolate = CcTest::isolate();
13329 v8::HandleScope scope(isolate);
13330 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13331 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
13332 ForceSetInterceptGetter, ForceSetInterceptSetter));
13333 pass_on_get = true;
13334 LocalContext context(NULL, templ);
13335 v8::Handle<v8::Object> global = context->Global();
13337 force_set_get_count = 0;
13338 force_set_set_count = 0;
13339 pass_on_get = false;
13341 v8::Handle<v8::String> some_property =
13342 v8::String::NewFromUtf8(isolate, "a");
13343 CHECK_EQ(0, force_set_set_count);
13344 CHECK_EQ(0, force_set_get_count);
13345 CHECK_EQ(3, global->Get(some_property)->Int32Value());
13346 // Setting the property shouldn't override it, just call the setter
13347 // which in this case does nothing.
13348 global->Set(some_property, v8::Int32::New(isolate, 7));
13349 CHECK_EQ(3, global->Get(some_property)->Int32Value());
13350 CHECK_EQ(1, force_set_set_count);
13351 CHECK_EQ(2, force_set_get_count);
13352 // Getting the property when the interceptor returns an empty handle
13353 // should yield undefined, since the property isn't present on the
13354 // object itself yet.
13355 pass_on_get = true;
13356 CHECK(global->Get(some_property)->IsUndefined());
13357 CHECK_EQ(1, force_set_set_count);
13358 CHECK_EQ(3, force_set_get_count);
13359 // Forcing the property to be set should cause the value to be
13360 // set locally without calling the interceptor.
13361 global->ForceSet(some_property, v8::Int32::New(isolate, 8));
13362 CHECK_EQ(8, global->Get(some_property)->Int32Value());
13363 CHECK_EQ(1, force_set_set_count);
13364 CHECK_EQ(4, force_set_get_count);
13365 // Reenabling the interceptor should cause it to take precedence over
13367 pass_on_get = false;
13368 CHECK_EQ(3, global->Get(some_property)->Int32Value());
13369 CHECK_EQ(1, force_set_set_count);
13370 CHECK_EQ(5, force_set_get_count);
13371 // The interceptor should also work for other properties
13372 CHECK_EQ(3, global->Get(v8::String::NewFromUtf8(isolate, "b"))
13374 CHECK_EQ(1, force_set_set_count);
13375 CHECK_EQ(6, force_set_get_count);
13379 TEST(CreateDataProperty) {
13381 v8::Isolate* isolate = env->GetIsolate();
13382 v8::HandleScope handle_scope(isolate);
13387 "Object.defineProperty(a, 'foo', {value: 23});"
13388 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
13390 v8::Local<v8::Object> obj =
13391 v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
13392 v8::Local<v8::Array> arr =
13393 v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
13395 // Can't change a non-configurable properties.
13396 v8::TryCatch try_catch(isolate);
13397 CHECK(!obj->CreateDataProperty(env.local(), v8_str("foo"),
13398 v8::Integer::New(isolate, 42)).FromJust());
13399 CHECK(!try_catch.HasCaught());
13400 CHECK(obj->CreateDataProperty(env.local(), v8_str("bar"),
13401 v8::Integer::New(isolate, 42)).FromJust());
13402 CHECK(!try_catch.HasCaught());
13403 v8::Local<v8::Value> val =
13404 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
13405 CHECK(val->IsNumber());
13406 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13410 // Set a regular property.
13411 v8::TryCatch try_catch(isolate);
13412 CHECK(obj->CreateDataProperty(env.local(), v8_str("blub"),
13413 v8::Integer::New(isolate, 42)).FromJust());
13414 CHECK(!try_catch.HasCaught());
13415 v8::Local<v8::Value> val =
13416 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
13417 CHECK(val->IsNumber());
13418 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13422 // Set an indexed property.
13423 v8::TryCatch try_catch(isolate);
13424 CHECK(obj->CreateDataProperty(env.local(), v8_str("1"),
13425 v8::Integer::New(isolate, 42)).FromJust());
13426 CHECK(!try_catch.HasCaught());
13427 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
13428 CHECK(val->IsNumber());
13429 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13433 // Special cases for arrays.
13434 v8::TryCatch try_catch(isolate);
13435 CHECK(!arr->CreateDataProperty(env.local(), v8_str("length"),
13436 v8::Integer::New(isolate, 1)).FromJust());
13437 CHECK(!try_catch.HasCaught());
13440 // Special cases for arrays: index exceeds the array's length
13441 v8::TryCatch try_catch(isolate);
13442 CHECK(arr->CreateDataProperty(env.local(), 1, v8::Integer::New(isolate, 23))
13444 CHECK(!try_catch.HasCaught());
13445 CHECK_EQ(2U, arr->Length());
13446 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
13447 CHECK(val->IsNumber());
13448 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
13450 // Set an existing entry.
13451 CHECK(arr->CreateDataProperty(env.local(), 0, v8::Integer::New(isolate, 42))
13453 CHECK(!try_catch.HasCaught());
13454 val = arr->Get(env.local(), 0).ToLocalChecked();
13455 CHECK(val->IsNumber());
13456 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13459 CompileRun("Object.freeze(a);");
13461 // Can't change non-extensible objects.
13462 v8::TryCatch try_catch(isolate);
13463 CHECK(!obj->CreateDataProperty(env.local(), v8_str("baz"),
13464 v8::Integer::New(isolate, 42)).FromJust());
13465 CHECK(!try_catch.HasCaught());
13468 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13469 templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
13470 v8::Local<v8::Object> access_checked =
13471 templ->NewInstance(env.local()).ToLocalChecked();
13473 v8::TryCatch try_catch(isolate);
13474 CHECK(access_checked->CreateDataProperty(env.local(), v8_str("foo"),
13475 v8::Integer::New(isolate, 42))
13477 CHECK(try_catch.HasCaught());
13482 TEST(DefineOwnProperty) {
13484 v8::Isolate* isolate = env->GetIsolate();
13485 v8::HandleScope handle_scope(isolate);
13490 "Object.defineProperty(a, 'foo', {value: 23});"
13491 "Object.defineProperty(a, 'bar', {value: 23, configurable: true});");
13493 v8::Local<v8::Object> obj =
13494 v8::Local<v8::Object>::Cast(env->Global()->Get(v8_str("a")));
13495 v8::Local<v8::Array> arr =
13496 v8::Local<v8::Array>::Cast(env->Global()->Get(v8_str("b")));
13498 // Can't change a non-configurable properties.
13499 v8::TryCatch try_catch(isolate);
13500 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("foo"),
13501 v8::Integer::New(isolate, 42)).FromJust());
13502 CHECK(!try_catch.HasCaught());
13503 CHECK(obj->DefineOwnProperty(env.local(), v8_str("bar"),
13504 v8::Integer::New(isolate, 42)).FromJust());
13505 CHECK(!try_catch.HasCaught());
13506 v8::Local<v8::Value> val =
13507 obj->Get(env.local(), v8_str("bar")).ToLocalChecked();
13508 CHECK(val->IsNumber());
13509 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13513 // Set a regular property.
13514 v8::TryCatch try_catch(isolate);
13515 CHECK(obj->DefineOwnProperty(env.local(), v8_str("blub"),
13516 v8::Integer::New(isolate, 42)).FromJust());
13517 CHECK(!try_catch.HasCaught());
13518 v8::Local<v8::Value> val =
13519 obj->Get(env.local(), v8_str("blub")).ToLocalChecked();
13520 CHECK(val->IsNumber());
13521 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13525 // Set an indexed property.
13526 v8::TryCatch try_catch(isolate);
13527 CHECK(obj->DefineOwnProperty(env.local(), v8_str("1"),
13528 v8::Integer::New(isolate, 42)).FromJust());
13529 CHECK(!try_catch.HasCaught());
13530 v8::Local<v8::Value> val = obj->Get(env.local(), 1).ToLocalChecked();
13531 CHECK(val->IsNumber());
13532 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13536 // Special cases for arrays.
13537 v8::TryCatch try_catch(isolate);
13538 CHECK(!arr->DefineOwnProperty(env.local(), v8_str("length"),
13539 v8::Integer::New(isolate, 1)).FromJust());
13540 CHECK(!try_catch.HasCaught());
13543 // Special cases for arrays: index exceeds the array's length
13544 v8::TryCatch try_catch(isolate);
13545 CHECK(arr->DefineOwnProperty(env.local(), v8_str("1"),
13546 v8::Integer::New(isolate, 23)).FromJust());
13547 CHECK(!try_catch.HasCaught());
13548 CHECK_EQ(2U, arr->Length());
13549 v8::Local<v8::Value> val = arr->Get(env.local(), 1).ToLocalChecked();
13550 CHECK(val->IsNumber());
13551 CHECK_EQ(23.0, val->NumberValue(env.local()).FromJust());
13553 // Set an existing entry.
13554 CHECK(arr->DefineOwnProperty(env.local(), v8_str("0"),
13555 v8::Integer::New(isolate, 42)).FromJust());
13556 CHECK(!try_catch.HasCaught());
13557 val = arr->Get(env.local(), 0).ToLocalChecked();
13558 CHECK(val->IsNumber());
13559 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13563 // Set a non-writable property.
13564 v8::TryCatch try_catch(isolate);
13565 CHECK(obj->DefineOwnProperty(env.local(), v8_str("lala"),
13566 v8::Integer::New(isolate, 42),
13567 v8::ReadOnly).FromJust());
13568 CHECK(!try_catch.HasCaught());
13569 v8::Local<v8::Value> val =
13570 obj->Get(env.local(), v8_str("lala")).ToLocalChecked();
13571 CHECK(val->IsNumber());
13572 CHECK_EQ(42.0, val->NumberValue(env.local()).FromJust());
13573 CHECK_EQ(v8::ReadOnly, obj->GetPropertyAttributes(
13574 env.local(), v8_str("lala")).FromJust());
13575 CHECK(!try_catch.HasCaught());
13578 CompileRun("Object.freeze(a);");
13580 // Can't change non-extensible objects.
13581 v8::TryCatch try_catch(isolate);
13582 CHECK(!obj->DefineOwnProperty(env.local(), v8_str("baz"),
13583 v8::Integer::New(isolate, 42)).FromJust());
13584 CHECK(!try_catch.HasCaught());
13587 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
13588 templ->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
13589 v8::Local<v8::Object> access_checked =
13590 templ->NewInstance(env.local()).ToLocalChecked();
13592 v8::TryCatch try_catch(isolate);
13593 CHECK(access_checked->DefineOwnProperty(env.local(), v8_str("foo"),
13594 v8::Integer::New(isolate, 42))
13596 CHECK(try_catch.HasCaught());
13601 static v8::Local<Context> calling_context0;
13602 static v8::Local<Context> calling_context1;
13603 static v8::Local<Context> calling_context2;
13606 // Check that the call to the callback is initiated in
13607 // calling_context2, the directly calling context is calling_context1
13608 // and the callback itself is in calling_context0.
13609 static void GetCallingContextCallback(
13610 const v8::FunctionCallbackInfo<v8::Value>& args) {
13611 ApiTestFuzzer::Fuzz();
13612 CHECK(args.GetIsolate()->GetCurrentContext() == calling_context0);
13613 CHECK(args.GetIsolate()->GetCallingContext() == calling_context1);
13614 CHECK(args.GetIsolate()->GetEnteredContext() == calling_context2);
13615 args.GetReturnValue().Set(42);
13619 THREADED_TEST(GetCurrentContextWhenNotInContext) {
13620 i::Isolate* isolate = CcTest::i_isolate();
13621 CHECK(isolate != NULL);
13622 CHECK(isolate->context() == NULL);
13623 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
13624 v8::HandleScope scope(v8_isolate);
13625 // The following should not crash, but return an empty handle.
13626 v8::Local<v8::Context> current = v8_isolate->GetCurrentContext();
13627 CHECK(current.IsEmpty());
13631 THREADED_TEST(GetCallingContext) {
13632 v8::Isolate* isolate = CcTest::isolate();
13633 v8::HandleScope scope(isolate);
13635 Local<Context> calling_context0(Context::New(isolate));
13636 Local<Context> calling_context1(Context::New(isolate));
13637 Local<Context> calling_context2(Context::New(isolate));
13638 ::calling_context0 = calling_context0;
13639 ::calling_context1 = calling_context1;
13640 ::calling_context2 = calling_context2;
13642 // Allow cross-domain access.
13643 Local<String> token = v8_str("<security token>");
13644 calling_context0->SetSecurityToken(token);
13645 calling_context1->SetSecurityToken(token);
13646 calling_context2->SetSecurityToken(token);
13648 // Create an object with a C++ callback in context0.
13649 calling_context0->Enter();
13650 Local<v8::FunctionTemplate> callback_templ =
13651 v8::FunctionTemplate::New(isolate, GetCallingContextCallback);
13652 calling_context0->Global()->Set(v8_str("callback"),
13653 callback_templ->GetFunction());
13654 calling_context0->Exit();
13656 // Expose context0 in context1 and set up a function that calls the
13657 // callback function.
13658 calling_context1->Enter();
13659 calling_context1->Global()->Set(v8_str("context0"),
13660 calling_context0->Global());
13661 CompileRun("function f() { context0.callback() }");
13662 calling_context1->Exit();
13664 // Expose context1 in context2 and call the callback function in
13665 // context0 indirectly through f in context1.
13666 calling_context2->Enter();
13667 calling_context2->Global()->Set(v8_str("context1"),
13668 calling_context1->Global());
13669 CompileRun("context1.f()");
13670 calling_context2->Exit();
13671 ::calling_context0.Clear();
13672 ::calling_context1.Clear();
13673 ::calling_context2.Clear();
13677 // Check that a variable declaration with no explicit initialization
13678 // value does shadow an existing property in the prototype chain.
13679 THREADED_TEST(InitGlobalVarInProtoChain) {
13680 LocalContext context;
13681 v8::HandleScope scope(context->GetIsolate());
13682 // Introduce a variable in the prototype chain.
13683 CompileRun("__proto__.x = 42");
13684 v8::Handle<v8::Value> result = CompileRun("var x = 43; x");
13685 CHECK(!result->IsUndefined());
13686 CHECK_EQ(43, result->Int32Value());
13690 // Regression test for issue 398.
13691 // If a function is added to an object, creating a constant function
13692 // field, and the result is cloned, replacing the constant function on the
13693 // original should not affect the clone.
13694 // See http://code.google.com/p/v8/issues/detail?id=398
13695 THREADED_TEST(ReplaceConstantFunction) {
13696 LocalContext context;
13697 v8::Isolate* isolate = context->GetIsolate();
13698 v8::HandleScope scope(isolate);
13699 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
13700 v8::Handle<v8::FunctionTemplate> func_templ =
13701 v8::FunctionTemplate::New(isolate);
13702 v8::Handle<v8::String> foo_string =
13703 v8::String::NewFromUtf8(isolate, "foo");
13704 obj->Set(foo_string, func_templ->GetFunction());
13705 v8::Handle<v8::Object> obj_clone = obj->Clone();
13706 obj_clone->Set(foo_string,
13707 v8::String::NewFromUtf8(isolate, "Hello"));
13708 CHECK(!obj->Get(foo_string)->IsUndefined());
13712 static void CheckElementValue(i::Isolate* isolate,
13714 i::Handle<i::Object> obj,
13716 i::Object* element =
13717 *i::Object::GetElement(isolate, obj, offset).ToHandleChecked();
13718 CHECK_EQ(expected, i::Smi::cast(element)->value());
13722 template <class ExternalArrayClass, class ElementType>
13723 static void ObjectWithExternalArrayTestHelper(Handle<Context> context,
13724 v8::Handle<Object> obj,
13726 i::ExternalArrayType array_type,
13727 int64_t low, int64_t high) {
13728 i::Handle<i::JSObject> jsobj = v8::Utils::OpenHandle(*obj);
13729 i::Isolate* isolate = jsobj->GetIsolate();
13730 obj->Set(v8_str("field"),
13731 v8::Int32::New(reinterpret_cast<v8::Isolate*>(isolate), 1503));
13732 context->Global()->Set(v8_str("ext_array"), obj);
13733 v8::Handle<v8::Value> result = CompileRun("ext_array.field");
13734 CHECK_EQ(1503, result->Int32Value());
13735 result = CompileRun("ext_array[1]");
13736 CHECK_EQ(1, result->Int32Value());
13738 // Check assigned smis
13739 result = CompileRun("for (var i = 0; i < 8; i++) {"
13740 " ext_array[i] = i;"
13743 "for (var i = 0; i < 8; i++) {"
13744 " sum += ext_array[i];"
13748 CHECK_EQ(28, result->Int32Value());
13749 // Check pass through of assigned smis
13750 result = CompileRun("var sum = 0;"
13751 "for (var i = 0; i < 8; i++) {"
13752 " sum += ext_array[i] = ext_array[i] = -i;"
13755 CHECK_EQ(-28, result->Int32Value());
13758 // Check assigned smis in reverse order
13759 result = CompileRun("for (var i = 8; --i >= 0; ) {"
13760 " ext_array[i] = i;"
13763 "for (var i = 0; i < 8; i++) {"
13764 " sum += ext_array[i];"
13767 CHECK_EQ(28, result->Int32Value());
13769 // Check pass through of assigned HeapNumbers
13770 result = CompileRun("var sum = 0;"
13771 "for (var i = 0; i < 16; i+=2) {"
13772 " sum += ext_array[i] = ext_array[i] = (-i * 0.5);"
13775 CHECK_EQ(-28, result->Int32Value());
13777 // Check assigned HeapNumbers
13778 result = CompileRun("for (var i = 0; i < 16; i+=2) {"
13779 " ext_array[i] = (i * 0.5);"
13782 "for (var i = 0; i < 16; i+=2) {"
13783 " sum += ext_array[i];"
13786 CHECK_EQ(28, result->Int32Value());
13788 // Check assigned HeapNumbers in reverse order
13789 result = CompileRun("for (var i = 14; i >= 0; i-=2) {"
13790 " ext_array[i] = (i * 0.5);"
13793 "for (var i = 0; i < 16; i+=2) {"
13794 " sum += ext_array[i];"
13797 CHECK_EQ(28, result->Int32Value());
13799 i::ScopedVector<char> test_buf(1024);
13801 // Check legal boundary conditions.
13802 // The repeated loads and stores ensure the ICs are exercised.
13803 const char* boundary_program =
13805 "for (var i = 0; i < 16; i++) {"
13806 " ext_array[i] = %lld;"
13808 " res = ext_array[i];"
13812 i::SNPrintF(test_buf,
13815 result = CompileRun(test_buf.start());
13816 CHECK_EQ(low, result->IntegerValue());
13818 i::SNPrintF(test_buf,
13821 result = CompileRun(test_buf.start());
13822 CHECK_EQ(high, result->IntegerValue());
13824 // Check misprediction of type in IC.
13825 result = CompileRun("var tmp_array = ext_array;"
13827 "for (var i = 0; i < 8; i++) {"
13828 " tmp_array[i] = i;"
13829 " sum += tmp_array[i];"
13835 // Force GC to trigger verification.
13836 CcTest::heap()->CollectAllGarbage();
13837 CHECK_EQ(28, result->Int32Value());
13839 // Make sure out-of-range loads do not throw.
13840 i::SNPrintF(test_buf,
13841 "var caught_exception = false;"
13845 " caught_exception = true;"
13847 "caught_exception;",
13849 result = CompileRun(test_buf.start());
13850 CHECK_EQ(false, result->BooleanValue());
13852 // Make sure out-of-range stores do not throw.
13853 i::SNPrintF(test_buf,
13854 "var caught_exception = false;"
13856 " ext_array[%d] = 1;"
13858 " caught_exception = true;"
13860 "caught_exception;",
13862 result = CompileRun(test_buf.start());
13863 CHECK_EQ(false, result->BooleanValue());
13865 // Check other boundary conditions, values and operations.
13866 result = CompileRun("for (var i = 0; i < 8; i++) {"
13867 " ext_array[7] = undefined;"
13870 CHECK_EQ(0, result->Int32Value());
13871 if (array_type == i::kExternalFloat64Array ||
13872 array_type == i::kExternalFloat32Array) {
13874 i::Object::GetElement(isolate, jsobj, 7).ToHandleChecked()->Number()));
13876 CheckElementValue(isolate, 0, jsobj, 7);
13879 result = CompileRun("for (var i = 0; i < 8; i++) {"
13880 " ext_array[6] = '2.3';"
13883 CHECK_EQ(2, result->Int32Value());
13886 i::Object::GetElement(
13887 isolate, jsobj, 6).ToHandleChecked()->Number()));
13889 if (array_type != i::kExternalFloat32Array &&
13890 array_type != i::kExternalFloat64Array) {
13891 // Though the specification doesn't state it, be explicit about
13892 // converting NaNs and +/-Infinity to zero.
13893 result = CompileRun("for (var i = 0; i < 8; i++) {"
13894 " ext_array[i] = 5;"
13896 "for (var i = 0; i < 8; i++) {"
13897 " ext_array[i] = NaN;"
13900 CHECK_EQ(0, result->Int32Value());
13901 CheckElementValue(isolate, 0, jsobj, 5);
13903 result = CompileRun("for (var i = 0; i < 8; i++) {"
13904 " ext_array[i] = 5;"
13906 "for (var i = 0; i < 8; i++) {"
13907 " ext_array[i] = Infinity;"
13910 int expected_value =
13911 (array_type == i::kExternalUint8ClampedArray) ? 255 : 0;
13912 CHECK_EQ(expected_value, result->Int32Value());
13913 CheckElementValue(isolate, expected_value, jsobj, 5);
13915 result = CompileRun("for (var i = 0; i < 8; i++) {"
13916 " ext_array[i] = 5;"
13918 "for (var i = 0; i < 8; i++) {"
13919 " ext_array[i] = -Infinity;"
13922 CHECK_EQ(0, result->Int32Value());
13923 CheckElementValue(isolate, 0, jsobj, 5);
13925 // Check truncation behavior of integral arrays.
13926 const char* unsigned_data =
13927 "var source_data = [0.6, 10.6];"
13928 "var expected_results = [0, 10];";
13929 const char* signed_data =
13930 "var source_data = [0.6, 10.6, -0.6, -10.6];"
13931 "var expected_results = [0, 10, 0, -10];";
13932 const char* pixel_data =
13933 "var source_data = [0.6, 10.6];"
13934 "var expected_results = [1, 11];";
13935 bool is_unsigned = (array_type == i::kExternalUint8Array ||
13936 array_type == i::kExternalUint16Array ||
13937 array_type == i::kExternalUint32Array);
13938 bool is_pixel_data = array_type == i::kExternalUint8ClampedArray;
13940 i::SNPrintF(test_buf,
13942 "var all_passed = true;"
13943 "for (var i = 0; i < source_data.length; i++) {"
13944 " for (var j = 0; j < 8; j++) {"
13945 " ext_array[j] = source_data[i];"
13947 " all_passed = all_passed &&"
13948 " (ext_array[5] == expected_results[i]);"
13953 (is_pixel_data ? pixel_data : signed_data)));
13954 result = CompileRun(test_buf.start());
13955 CHECK_EQ(true, result->BooleanValue());
13958 i::Handle<ExternalArrayClass> array(
13959 ExternalArrayClass::cast(jsobj->elements()));
13960 for (int i = 0; i < element_count; i++) {
13961 array->set(i, static_cast<ElementType>(i));
13964 // Test complex assignments
13965 result = CompileRun("function ee_op_test_complex_func(sum) {"
13966 " for (var i = 0; i < 40; ++i) {"
13967 " sum += (ext_array[i] += 1);"
13968 " sum += (ext_array[i] -= 1);"
13973 "for (var i=0;i<10000;++i) {"
13974 " sum=ee_op_test_complex_func(sum);"
13977 CHECK_EQ(16000000, result->Int32Value());
13979 // Test count operations
13980 result = CompileRun("function ee_op_test_count_func(sum) {"
13981 " for (var i = 0; i < 40; ++i) {"
13982 " sum += (++ext_array[i]);"
13983 " sum += (--ext_array[i]);"
13988 "for (var i=0;i<10000;++i) {"
13989 " sum=ee_op_test_count_func(sum);"
13992 CHECK_EQ(16000000, result->Int32Value());
13994 result = CompileRun("ext_array[3] = 33;"
13995 "delete ext_array[3];"
13997 CHECK_EQ(33, result->Int32Value());
13999 result = CompileRun("ext_array[0] = 10; ext_array[1] = 11;"
14000 "ext_array[2] = 12; ext_array[3] = 13;"
14001 "ext_array.__defineGetter__('2',"
14002 "function() { return 120; });"
14004 CHECK_EQ(12, result->Int32Value());
14006 result = CompileRun("var js_array = new Array(40);"
14007 "js_array[0] = 77;"
14009 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14011 result = CompileRun("ext_array[1] = 23;"
14012 "ext_array.__proto__ = [];"
14013 "js_array.__proto__ = ext_array;"
14014 "js_array.concat(ext_array);");
14015 CHECK_EQ(77, v8::Object::Cast(*result)->Get(v8_str("0"))->Int32Value());
14016 CHECK_EQ(23, v8::Object::Cast(*result)->Get(v8_str("1"))->Int32Value());
14018 result = CompileRun("ext_array[1] = 23;");
14019 CHECK_EQ(23, result->Int32Value());
14023 template <class FixedTypedArrayClass, i::ElementsKind elements_kind,
14025 static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type,
14026 ElementType low, ElementType high) {
14027 i::FLAG_allow_natives_syntax = true;
14028 LocalContext context;
14029 i::Isolate* isolate = CcTest::i_isolate();
14030 i::Factory* factory = isolate->factory();
14031 v8::HandleScope scope(context->GetIsolate());
14032 const int kElementCount = 260;
14033 i::Handle<i::JSTypedArray> jsobj =
14034 factory->NewJSTypedArray(elements_kind, kElementCount);
14035 i::Handle<FixedTypedArrayClass> fixed_array(
14036 FixedTypedArrayClass::cast(jsobj->elements()));
14037 CHECK_EQ(FixedTypedArrayClass::kInstanceType,
14038 fixed_array->map()->instance_type());
14039 CHECK_EQ(kElementCount, fixed_array->length());
14040 CcTest::heap()->CollectAllGarbage();
14041 for (int i = 0; i < kElementCount; i++) {
14042 fixed_array->set(i, static_cast<ElementType>(i));
14044 // Force GC to trigger verification.
14045 CcTest::heap()->CollectAllGarbage();
14046 for (int i = 0; i < kElementCount; i++) {
14047 CHECK_EQ(static_cast<int64_t>(static_cast<ElementType>(i)),
14048 static_cast<int64_t>(fixed_array->get_scalar(i)));
14050 v8::Handle<v8::Object> obj = v8::Utils::ToLocal(jsobj);
14052 ObjectWithExternalArrayTestHelper<FixedTypedArrayClass, ElementType>(
14053 context.local(), obj, kElementCount, array_type,
14054 static_cast<int64_t>(low),
14055 static_cast<int64_t>(high));
14059 THREADED_TEST(FixedUint8Array) {
14060 FixedTypedArrayTestHelper<i::FixedUint8Array, i::UINT8_ELEMENTS, uint8_t>(
14061 i::kExternalUint8Array, 0x0, 0xFF);
14065 THREADED_TEST(FixedUint8ClampedArray) {
14066 FixedTypedArrayTestHelper<i::FixedUint8ClampedArray,
14067 i::UINT8_CLAMPED_ELEMENTS, uint8_t>(
14068 i::kExternalUint8ClampedArray, 0x0, 0xFF);
14072 THREADED_TEST(FixedInt8Array) {
14073 FixedTypedArrayTestHelper<i::FixedInt8Array, i::INT8_ELEMENTS, int8_t>(
14074 i::kExternalInt8Array, -0x80, 0x7F);
14078 THREADED_TEST(FixedUint16Array) {
14079 FixedTypedArrayTestHelper<i::FixedUint16Array, i::UINT16_ELEMENTS, uint16_t>(
14080 i::kExternalUint16Array, 0x0, 0xFFFF);
14084 THREADED_TEST(FixedInt16Array) {
14085 FixedTypedArrayTestHelper<i::FixedInt16Array, i::INT16_ELEMENTS, int16_t>(
14086 i::kExternalInt16Array, -0x8000, 0x7FFF);
14090 THREADED_TEST(FixedUint32Array) {
14091 FixedTypedArrayTestHelper<i::FixedUint32Array, i::UINT32_ELEMENTS, uint32_t>(
14092 i::kExternalUint32Array, 0x0, UINT_MAX);
14096 THREADED_TEST(FixedInt32Array) {
14097 FixedTypedArrayTestHelper<i::FixedInt32Array, i::INT32_ELEMENTS, int32_t>(
14098 i::kExternalInt32Array, INT_MIN, INT_MAX);
14102 THREADED_TEST(FixedFloat32Array) {
14103 FixedTypedArrayTestHelper<i::FixedFloat32Array, i::FLOAT32_ELEMENTS, float>(
14104 i::kExternalFloat32Array, -500, 500);
14108 THREADED_TEST(FixedFloat64Array) {
14109 FixedTypedArrayTestHelper<i::FixedFloat64Array, i::FLOAT64_ELEMENTS, float>(
14110 i::kExternalFloat64Array, -500, 500);
14114 template <typename ElementType, typename TypedArray, class ExternalArrayClass,
14115 class ArrayBufferType>
14116 void TypedArrayTestHelper(i::ExternalArrayType array_type, int64_t low,
14118 const int kElementCount = 50;
14120 i::ScopedVector<ElementType> backing_store(kElementCount+2);
14123 v8::Isolate* isolate = env->GetIsolate();
14124 v8::HandleScope handle_scope(isolate);
14126 Local<ArrayBufferType> ab =
14127 ArrayBufferType::New(isolate, backing_store.start(),
14128 (kElementCount + 2) * sizeof(ElementType));
14129 Local<TypedArray> ta =
14130 TypedArray::New(ab, 2*sizeof(ElementType), kElementCount);
14131 CheckInternalFieldsAreZero<v8::ArrayBufferView>(ta);
14132 CHECK_EQ(kElementCount, static_cast<int>(ta->Length()));
14133 CHECK_EQ(2 * sizeof(ElementType), ta->ByteOffset());
14134 CHECK_EQ(kElementCount * sizeof(ElementType), ta->ByteLength());
14135 CHECK(ab->Equals(ta->Buffer()));
14137 ElementType* data = backing_store.start() + 2;
14138 for (int i = 0; i < kElementCount; i++) {
14139 data[i] = static_cast<ElementType>(i);
14142 ObjectWithExternalArrayTestHelper<ExternalArrayClass, ElementType>(
14143 env.local(), ta, kElementCount, array_type, low, high);
14147 THREADED_TEST(Uint8Array) {
14148 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
14149 v8::ArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
14153 THREADED_TEST(Int8Array) {
14154 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
14155 v8::ArrayBuffer>(i::kExternalInt8Array, -0x80, 0x7F);
14159 THREADED_TEST(Uint16Array) {
14160 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
14161 v8::ArrayBuffer>(i::kExternalUint16Array, 0, 0xFFFF);
14165 THREADED_TEST(Int16Array) {
14166 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
14167 v8::ArrayBuffer>(i::kExternalInt16Array, -0x8000,
14172 THREADED_TEST(Uint32Array) {
14173 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
14174 v8::ArrayBuffer>(i::kExternalUint32Array, 0, UINT_MAX);
14178 THREADED_TEST(Int32Array) {
14179 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
14180 v8::ArrayBuffer>(i::kExternalInt32Array, INT_MIN,
14185 THREADED_TEST(Float32Array) {
14186 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
14187 v8::ArrayBuffer>(i::kExternalFloat32Array, -500, 500);
14191 THREADED_TEST(Float64Array) {
14192 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
14193 v8::ArrayBuffer>(i::kExternalFloat64Array, -500, 500);
14197 THREADED_TEST(Uint8ClampedArray) {
14198 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
14199 i::FixedUint8ClampedArray, v8::ArrayBuffer>(
14200 i::kExternalUint8ClampedArray, 0, 0xFF);
14204 THREADED_TEST(DataView) {
14205 const int kSize = 50;
14207 i::ScopedVector<uint8_t> backing_store(kSize+2);
14210 v8::Isolate* isolate = env->GetIsolate();
14211 v8::HandleScope handle_scope(isolate);
14213 Local<v8::ArrayBuffer> ab =
14214 v8::ArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
14215 Local<v8::DataView> dv = v8::DataView::New(ab, 2, kSize);
14216 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
14217 CHECK_EQ(2u, dv->ByteOffset());
14218 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
14219 CHECK(ab->Equals(dv->Buffer()));
14223 THREADED_TEST(SharedUint8Array) {
14224 i::FLAG_harmony_sharedarraybuffer = true;
14225 TypedArrayTestHelper<uint8_t, v8::Uint8Array, i::FixedUint8Array,
14226 v8::SharedArrayBuffer>(i::kExternalUint8Array, 0, 0xFF);
14230 THREADED_TEST(SharedInt8Array) {
14231 i::FLAG_harmony_sharedarraybuffer = true;
14232 TypedArrayTestHelper<int8_t, v8::Int8Array, i::FixedInt8Array,
14233 v8::SharedArrayBuffer>(i::kExternalInt8Array, -0x80,
14238 THREADED_TEST(SharedUint16Array) {
14239 i::FLAG_harmony_sharedarraybuffer = true;
14240 TypedArrayTestHelper<uint16_t, v8::Uint16Array, i::FixedUint16Array,
14241 v8::SharedArrayBuffer>(i::kExternalUint16Array, 0,
14246 THREADED_TEST(SharedInt16Array) {
14247 i::FLAG_harmony_sharedarraybuffer = true;
14248 TypedArrayTestHelper<int16_t, v8::Int16Array, i::FixedInt16Array,
14249 v8::SharedArrayBuffer>(i::kExternalInt16Array, -0x8000,
14254 THREADED_TEST(SharedUint32Array) {
14255 i::FLAG_harmony_sharedarraybuffer = true;
14256 TypedArrayTestHelper<uint32_t, v8::Uint32Array, i::FixedUint32Array,
14257 v8::SharedArrayBuffer>(i::kExternalUint32Array, 0,
14262 THREADED_TEST(SharedInt32Array) {
14263 i::FLAG_harmony_sharedarraybuffer = true;
14264 TypedArrayTestHelper<int32_t, v8::Int32Array, i::FixedInt32Array,
14265 v8::SharedArrayBuffer>(i::kExternalInt32Array, INT_MIN,
14270 THREADED_TEST(SharedFloat32Array) {
14271 i::FLAG_harmony_sharedarraybuffer = true;
14272 TypedArrayTestHelper<float, v8::Float32Array, i::FixedFloat32Array,
14273 v8::SharedArrayBuffer>(i::kExternalFloat32Array, -500,
14278 THREADED_TEST(SharedFloat64Array) {
14279 i::FLAG_harmony_sharedarraybuffer = true;
14280 TypedArrayTestHelper<double, v8::Float64Array, i::FixedFloat64Array,
14281 v8::SharedArrayBuffer>(i::kExternalFloat64Array, -500,
14286 THREADED_TEST(SharedUint8ClampedArray) {
14287 i::FLAG_harmony_sharedarraybuffer = true;
14288 TypedArrayTestHelper<uint8_t, v8::Uint8ClampedArray,
14289 i::FixedUint8ClampedArray, v8::SharedArrayBuffer>(
14290 i::kExternalUint8ClampedArray, 0, 0xFF);
14294 THREADED_TEST(SharedDataView) {
14295 i::FLAG_harmony_sharedarraybuffer = true;
14296 const int kSize = 50;
14298 i::ScopedVector<uint8_t> backing_store(kSize + 2);
14301 v8::Isolate* isolate = env->GetIsolate();
14302 v8::HandleScope handle_scope(isolate);
14304 Local<v8::SharedArrayBuffer> ab =
14305 v8::SharedArrayBuffer::New(isolate, backing_store.start(), 2 + kSize);
14306 Local<v8::DataView> dv =
14307 v8::DataView::New(ab, 2, kSize);
14308 CheckInternalFieldsAreZero<v8::ArrayBufferView>(dv);
14309 CHECK_EQ(2u, dv->ByteOffset());
14310 CHECK_EQ(kSize, static_cast<int>(dv->ByteLength()));
14311 CHECK(ab->Equals(dv->Buffer()));
14315 #define IS_ARRAY_BUFFER_VIEW_TEST(View) \
14316 THREADED_TEST(Is##View) { \
14317 LocalContext env; \
14318 v8::Isolate* isolate = env->GetIsolate(); \
14319 v8::HandleScope handle_scope(isolate); \
14321 Handle<Value> result = CompileRun( \
14322 "var ab = new ArrayBuffer(128);" \
14323 "new " #View "(ab)"); \
14324 CHECK(result->IsArrayBufferView()); \
14325 CHECK(result->Is##View()); \
14326 CheckInternalFieldsAreZero<v8::ArrayBufferView>(result.As<v8::View>()); \
14329 IS_ARRAY_BUFFER_VIEW_TEST(Uint8Array)
14330 IS_ARRAY_BUFFER_VIEW_TEST(Int8Array)
14331 IS_ARRAY_BUFFER_VIEW_TEST(Uint16Array)
14332 IS_ARRAY_BUFFER_VIEW_TEST(Int16Array)
14333 IS_ARRAY_BUFFER_VIEW_TEST(Uint32Array)
14334 IS_ARRAY_BUFFER_VIEW_TEST(Int32Array)
14335 IS_ARRAY_BUFFER_VIEW_TEST(Float32Array)
14336 IS_ARRAY_BUFFER_VIEW_TEST(Float64Array)
14337 IS_ARRAY_BUFFER_VIEW_TEST(Uint8ClampedArray)
14338 IS_ARRAY_BUFFER_VIEW_TEST(DataView)
14340 #undef IS_ARRAY_BUFFER_VIEW_TEST
14344 THREADED_TEST(ScriptContextDependence) {
14346 v8::HandleScope scope(c1->GetIsolate());
14347 const char *source = "foo";
14348 v8::Handle<v8::Script> dep = v8_compile(source);
14349 v8::ScriptCompiler::Source script_source(v8::String::NewFromUtf8(
14350 c1->GetIsolate(), source));
14351 v8::Handle<v8::UnboundScript> indep =
14352 v8::ScriptCompiler::CompileUnbound(c1->GetIsolate(), &script_source);
14353 c1->Global()->Set(v8::String::NewFromUtf8(c1->GetIsolate(), "foo"),
14354 v8::Integer::New(c1->GetIsolate(), 100));
14355 CHECK_EQ(dep->Run()->Int32Value(), 100);
14356 CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 100);
14358 c2->Global()->Set(v8::String::NewFromUtf8(c2->GetIsolate(), "foo"),
14359 v8::Integer::New(c2->GetIsolate(), 101));
14360 CHECK_EQ(dep->Run()->Int32Value(), 100);
14361 CHECK_EQ(indep->BindToCurrentContext()->Run()->Int32Value(), 101);
14365 THREADED_TEST(StackTrace) {
14366 LocalContext context;
14367 v8::HandleScope scope(context->GetIsolate());
14368 v8::TryCatch try_catch(context->GetIsolate());
14369 const char *source = "function foo() { FAIL.FAIL; }; foo();";
14370 v8::Handle<v8::String> src =
14371 v8::String::NewFromUtf8(context->GetIsolate(), source);
14372 v8::Handle<v8::String> origin =
14373 v8::String::NewFromUtf8(context->GetIsolate(), "stack-trace-test");
14374 v8::ScriptCompiler::Source script_source(src, v8::ScriptOrigin(origin));
14375 v8::ScriptCompiler::CompileUnbound(context->GetIsolate(), &script_source)
14376 ->BindToCurrentContext()
14378 CHECK(try_catch.HasCaught());
14379 v8::String::Utf8Value stack(try_catch.StackTrace());
14380 CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
14384 // Checks that a StackFrame has certain expected values.
14385 void checkStackFrame(const char* expected_script_name,
14386 const char* expected_func_name, int expected_line_number,
14387 int expected_column, bool is_eval, bool is_constructor,
14388 v8::Handle<v8::StackFrame> frame) {
14389 v8::HandleScope scope(CcTest::isolate());
14390 v8::String::Utf8Value func_name(frame->GetFunctionName());
14391 v8::String::Utf8Value script_name(frame->GetScriptName());
14392 if (*script_name == NULL) {
14393 // The situation where there is no associated script, like for evals.
14394 CHECK(expected_script_name == NULL);
14396 CHECK(strstr(*script_name, expected_script_name) != NULL);
14398 CHECK(strstr(*func_name, expected_func_name) != NULL);
14399 CHECK_EQ(expected_line_number, frame->GetLineNumber());
14400 CHECK_EQ(expected_column, frame->GetColumn());
14401 CHECK_EQ(is_eval, frame->IsEval());
14402 CHECK_EQ(is_constructor, frame->IsConstructor());
14406 void AnalyzeStackInNativeCode(const v8::FunctionCallbackInfo<v8::Value>& args) {
14407 v8::HandleScope scope(args.GetIsolate());
14408 const char* origin = "capture-stack-trace-test";
14409 const int kOverviewTest = 1;
14410 const int kDetailedTest = 2;
14412 DCHECK(args.Length() == 1);
14414 int testGroup = args[0]->Int32Value();
14415 if (testGroup == kOverviewTest) {
14416 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
14417 args.GetIsolate(), 10, v8::StackTrace::kOverview);
14418 CHECK_EQ(4, stackTrace->GetFrameCount());
14419 checkStackFrame(origin, "bar", 2, 10, false, false,
14420 stackTrace->GetFrame(0));
14421 checkStackFrame(origin, "foo", 6, 3, false, false,
14422 stackTrace->GetFrame(1));
14423 // This is the source string inside the eval which has the call to foo.
14424 checkStackFrame(NULL, "", 1, 1, false, false, stackTrace->GetFrame(2));
14425 // The last frame is an anonymous function which has the initial eval call.
14426 checkStackFrame(origin, "", 8, 7, false, false, stackTrace->GetFrame(3));
14428 CHECK(stackTrace->AsArray()->IsArray());
14429 } else if (testGroup == kDetailedTest) {
14430 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
14431 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
14432 CHECK_EQ(4, stackTrace->GetFrameCount());
14433 checkStackFrame(origin, "bat", 4, 22, false, false,
14434 stackTrace->GetFrame(0));
14435 checkStackFrame(origin, "baz", 8, 3, false, true,
14436 stackTrace->GetFrame(1));
14437 bool is_eval = true;
14438 // This is the source string inside the eval which has the call to baz.
14439 checkStackFrame(NULL, "", 1, 1, is_eval, false, stackTrace->GetFrame(2));
14440 // The last frame is an anonymous function which has the initial eval call.
14441 checkStackFrame(origin, "", 10, 1, false, false, stackTrace->GetFrame(3));
14443 CHECK(stackTrace->AsArray()->IsArray());
14448 // Tests the C++ StackTrace API.
14449 // TODO(3074796): Reenable this as a THREADED_TEST once it passes.
14450 // THREADED_TEST(CaptureStackTrace) {
14451 TEST(CaptureStackTrace) {
14452 v8::Isolate* isolate = CcTest::isolate();
14453 v8::HandleScope scope(isolate);
14454 v8::Handle<v8::String> origin =
14455 v8::String::NewFromUtf8(isolate, "capture-stack-trace-test");
14456 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
14457 templ->Set(v8_str("AnalyzeStackInNativeCode"),
14458 v8::FunctionTemplate::New(isolate, AnalyzeStackInNativeCode));
14459 LocalContext context(0, templ);
14461 // Test getting OVERVIEW information. Should ignore information that is not
14462 // script name, function name, line number, and column offset.
14463 const char *overview_source =
14464 "function bar() {\n"
14465 " var y; AnalyzeStackInNativeCode(1);\n"
14467 "function foo() {\n"
14471 "var x;eval('new foo();');";
14472 v8::Handle<v8::String> overview_src =
14473 v8::String::NewFromUtf8(isolate, overview_source);
14474 v8::ScriptCompiler::Source script_source(overview_src,
14475 v8::ScriptOrigin(origin));
14476 v8::Handle<Value> overview_result(
14477 v8::ScriptCompiler::CompileUnbound(isolate, &script_source)
14478 ->BindToCurrentContext()
14480 CHECK(!overview_result.IsEmpty());
14481 CHECK(overview_result->IsObject());
14483 // Test getting DETAILED information.
14484 const char *detailed_source =
14485 "function bat() {AnalyzeStackInNativeCode(2);\n"
14488 "function baz() {\n"
14491 "eval('new baz();');";
14492 v8::Handle<v8::String> detailed_src =
14493 v8::String::NewFromUtf8(isolate, detailed_source);
14494 // Make the script using a non-zero line and column offset.
14495 v8::Handle<v8::Integer> line_offset = v8::Integer::New(isolate, 3);
14496 v8::Handle<v8::Integer> column_offset = v8::Integer::New(isolate, 5);
14497 v8::ScriptOrigin detailed_origin(origin, line_offset, column_offset);
14498 v8::ScriptCompiler::Source script_source2(detailed_src, detailed_origin);
14499 v8::Handle<v8::UnboundScript> detailed_script(
14500 v8::ScriptCompiler::CompileUnbound(isolate, &script_source2));
14501 v8::Handle<Value> detailed_result(
14502 detailed_script->BindToCurrentContext()->Run());
14503 CHECK(!detailed_result.IsEmpty());
14504 CHECK(detailed_result->IsObject());
14508 static void StackTraceForUncaughtExceptionListener(
14509 v8::Handle<v8::Message> message,
14510 v8::Handle<Value>) {
14512 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14513 CHECK_EQ(2, stack_trace->GetFrameCount());
14514 checkStackFrame("origin", "foo", 2, 3, false, false,
14515 stack_trace->GetFrame(0));
14516 checkStackFrame("origin", "bar", 5, 3, false, false,
14517 stack_trace->GetFrame(1));
14521 TEST(CaptureStackTraceForUncaughtException) {
14524 v8::HandleScope scope(env->GetIsolate());
14525 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14526 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14528 CompileRunWithOrigin(
14529 "function foo() {\n"
14532 "function bar() {\n"
14536 v8::Local<v8::Object> global = env->Global();
14537 Local<Value> trouble = global->Get(v8_str("bar"));
14538 CHECK(trouble->IsFunction());
14539 Function::Cast(*trouble)->Call(global, 0, NULL);
14540 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14541 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14542 CHECK_EQ(1, report_count);
14546 TEST(GetStackTraceForUncaughtExceptionFromSimpleStackTrace) {
14549 v8::HandleScope scope(env->GetIsolate());
14551 // Create an Error object first.
14552 CompileRunWithOrigin(
14553 "function foo() {\n"
14554 "e=new Error('err');\n"
14556 "function bar() {\n"
14561 v8::Local<v8::Object> global = env->Global();
14562 Local<Value> trouble = global->Get(v8_str("bar"));
14563 CHECK(trouble->IsFunction());
14564 Function::Cast(*trouble)->Call(global, 0, NULL);
14566 // Enable capturing detailed stack trace late, and throw the exception.
14567 // The detailed stack trace should be extracted from the simple stack.
14568 v8::V8::AddMessageListener(StackTraceForUncaughtExceptionListener);
14569 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14570 CompileRunWithOrigin("throw e", "origin");
14571 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14572 v8::V8::RemoveMessageListeners(StackTraceForUncaughtExceptionListener);
14573 CHECK_EQ(1, report_count);
14577 TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
14579 v8::HandleScope scope(env->GetIsolate());
14580 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
14582 v8::StackTrace::kDetailed);
14585 "var setters = ['column', 'lineNumber', 'scriptName',\n"
14586 " 'scriptNameOrSourceURL', 'functionName', 'isEval',\n"
14587 " 'isConstructor'];\n"
14588 "for (var i = 0; i < setters.length; i++) {\n"
14589 " var prop = setters[i];\n"
14590 " Object.prototype.__defineSetter__(prop, function() { throw prop; });\n"
14592 CompileRun("throw 'exception';");
14593 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14597 static void StackTraceFunctionNameListener(v8::Handle<v8::Message> message,
14598 v8::Handle<Value>) {
14599 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14600 CHECK_EQ(5, stack_trace->GetFrameCount());
14601 checkStackFrame("origin", "foo:0", 4, 7, false, false,
14602 stack_trace->GetFrame(0));
14603 checkStackFrame("origin", "foo:1", 5, 27, false, false,
14604 stack_trace->GetFrame(1));
14605 checkStackFrame("origin", "foo", 5, 27, false, false,
14606 stack_trace->GetFrame(2));
14607 checkStackFrame("origin", "foo", 5, 27, false, false,
14608 stack_trace->GetFrame(3));
14609 checkStackFrame("origin", "", 1, 14, false, false, stack_trace->GetFrame(4));
14613 TEST(GetStackTraceContainsFunctionsWithFunctionName) {
14615 v8::HandleScope scope(env->GetIsolate());
14617 CompileRunWithOrigin(
14618 "function gen(name, counter) {\n"
14619 " var f = function foo() {\n"
14620 " if (counter === 0)\n"
14622 " gen(name, counter - 1)();\n"
14624 " if (counter == 3) {\n"
14625 " Object.defineProperty(f, 'name', {get: function(){ throw 239; }});\n"
14627 " Object.defineProperty(f, 'name', {writable:true});\n"
14628 " if (counter == 2)\n"
14631 " f.name = name + ':' + counter;\n"
14637 v8::V8::AddMessageListener(StackTraceFunctionNameListener);
14638 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14639 CompileRunWithOrigin("gen('foo', 3)();", "origin");
14640 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14641 v8::V8::RemoveMessageListeners(StackTraceFunctionNameListener);
14645 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
14646 v8::Handle<v8::Value> data) {
14647 // Use the frame where JavaScript is called from.
14648 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14649 CHECK(!stack_trace.IsEmpty());
14650 int frame_count = stack_trace->GetFrameCount();
14651 CHECK_EQ(3, frame_count);
14652 int line_number[] = {1, 2, 5};
14653 for (int i = 0; i < frame_count; i++) {
14654 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14659 // Test that we only return the stack trace at the site where the exception
14660 // is first thrown (not where it is rethrown).
14661 TEST(RethrowStackTrace) {
14663 v8::HandleScope scope(env->GetIsolate());
14664 // We make sure that
14665 // - the stack trace of the ReferenceError in g() is reported.
14666 // - the stack trace is not overwritten when e1 is rethrown by t().
14667 // - the stack trace of e2 does not overwrite that of e1.
14668 const char* source =
14669 "function g() { error; } \n"
14670 "function f() { g(); } \n"
14671 "function t(e) { throw e; } \n"
14674 "} catch (e1) { \n"
14677 " } catch (e2) { \n"
14681 v8::V8::AddMessageListener(RethrowStackTraceHandler);
14682 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14683 CompileRun(source);
14684 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14685 v8::V8::RemoveMessageListeners(RethrowStackTraceHandler);
14689 static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
14690 v8::Handle<v8::Value> data) {
14691 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14692 CHECK(!stack_trace.IsEmpty());
14693 int frame_count = stack_trace->GetFrameCount();
14694 CHECK_EQ(2, frame_count);
14695 int line_number[] = {3, 7};
14696 for (int i = 0; i < frame_count; i++) {
14697 CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
14702 // Test that we do not recognize identity for primitive exceptions.
14703 TEST(RethrowPrimitiveStackTrace) {
14705 v8::HandleScope scope(env->GetIsolate());
14706 // We do not capture stack trace for non Error objects on creation time.
14707 // Instead, we capture the stack trace on last throw.
14708 const char* source =
14709 "function g() { throw 404; } \n"
14710 "function f() { g(); } \n"
14711 "function t(e) { throw e; } \n"
14714 "} catch (e1) { \n"
14717 v8::V8::AddMessageListener(RethrowPrimitiveStackTraceHandler);
14718 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14719 CompileRun(source);
14720 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14721 v8::V8::RemoveMessageListeners(RethrowPrimitiveStackTraceHandler);
14725 static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
14726 v8::Handle<v8::Value> data) {
14727 // Use the frame where JavaScript is called from.
14728 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14729 CHECK(!stack_trace.IsEmpty());
14730 CHECK_EQ(1, stack_trace->GetFrameCount());
14731 CHECK_EQ(1, stack_trace->GetFrame(0)->GetLineNumber());
14735 // Test that the stack trace is captured when the error object is created and
14736 // not where it is thrown.
14737 TEST(RethrowExistingStackTrace) {
14739 v8::HandleScope scope(env->GetIsolate());
14740 const char* source =
14741 "var e = new Error(); \n"
14743 v8::V8::AddMessageListener(RethrowExistingStackTraceHandler);
14744 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14745 CompileRun(source);
14746 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14747 v8::V8::RemoveMessageListeners(RethrowExistingStackTraceHandler);
14751 static void RethrowBogusErrorStackTraceHandler(v8::Handle<v8::Message> message,
14752 v8::Handle<v8::Value> data) {
14753 // Use the frame where JavaScript is called from.
14754 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14755 CHECK(!stack_trace.IsEmpty());
14756 CHECK_EQ(1, stack_trace->GetFrameCount());
14757 CHECK_EQ(2, stack_trace->GetFrame(0)->GetLineNumber());
14761 // Test that the stack trace is captured where the bogus Error object is thrown.
14762 TEST(RethrowBogusErrorStackTrace) {
14764 v8::HandleScope scope(env->GetIsolate());
14765 const char* source =
14766 "var e = {__proto__: new Error()} \n"
14768 v8::V8::AddMessageListener(RethrowBogusErrorStackTraceHandler);
14769 v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
14770 CompileRun(source);
14771 v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
14772 v8::V8::RemoveMessageListeners(RethrowBogusErrorStackTraceHandler);
14776 v8::PromiseRejectEvent reject_event = v8::kPromiseRejectWithNoHandler;
14777 int promise_reject_counter = 0;
14778 int promise_revoke_counter = 0;
14779 int promise_reject_msg_line_number = -1;
14780 int promise_reject_msg_column_number = -1;
14781 int promise_reject_line_number = -1;
14782 int promise_reject_column_number = -1;
14783 int promise_reject_frame_count = -1;
14785 void PromiseRejectCallback(v8::PromiseRejectMessage reject_message) {
14786 if (reject_message.GetEvent() == v8::kPromiseRejectWithNoHandler) {
14787 promise_reject_counter++;
14788 CcTest::global()->Set(v8_str("rejected"), reject_message.GetPromise());
14789 CcTest::global()->Set(v8_str("value"), reject_message.GetValue());
14790 v8::Handle<v8::Message> message =
14791 v8::Exception::CreateMessage(reject_message.GetValue());
14792 v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
14794 promise_reject_msg_line_number = message->GetLineNumber();
14795 promise_reject_msg_column_number = message->GetStartColumn() + 1;
14797 if (!stack_trace.IsEmpty()) {
14798 promise_reject_frame_count = stack_trace->GetFrameCount();
14799 if (promise_reject_frame_count > 0) {
14800 CHECK(stack_trace->GetFrame(0)->GetScriptName()->Equals(v8_str("pro")));
14801 promise_reject_line_number = stack_trace->GetFrame(0)->GetLineNumber();
14802 promise_reject_column_number = stack_trace->GetFrame(0)->GetColumn();
14804 promise_reject_line_number = -1;
14805 promise_reject_column_number = -1;
14809 promise_revoke_counter++;
14810 CcTest::global()->Set(v8_str("revoked"), reject_message.GetPromise());
14811 CHECK(reject_message.GetValue().IsEmpty());
14816 v8::Handle<v8::Promise> GetPromise(const char* name) {
14817 return v8::Handle<v8::Promise>::Cast(CcTest::global()->Get(v8_str(name)));
14821 v8::Handle<v8::Value> RejectValue() {
14822 return CcTest::global()->Get(v8_str("value"));
14826 void ResetPromiseStates() {
14827 promise_reject_counter = 0;
14828 promise_revoke_counter = 0;
14829 promise_reject_msg_line_number = -1;
14830 promise_reject_msg_column_number = -1;
14831 promise_reject_line_number = -1;
14832 promise_reject_column_number = -1;
14833 promise_reject_frame_count = -1;
14834 CcTest::global()->Set(v8_str("rejected"), v8_str(""));
14835 CcTest::global()->Set(v8_str("value"), v8_str(""));
14836 CcTest::global()->Set(v8_str("revoked"), v8_str(""));
14840 TEST(PromiseRejectCallback) {
14842 v8::Isolate* isolate = env->GetIsolate();
14843 v8::HandleScope scope(isolate);
14845 isolate->SetPromiseRejectCallback(PromiseRejectCallback);
14847 ResetPromiseStates();
14849 // Create promise p0.
14852 "var p0 = new Promise( \n"
14853 " function(res, rej) { \n"
14854 " reject = rej; \n"
14857 CHECK(!GetPromise("p0")->HasHandler());
14858 CHECK_EQ(0, promise_reject_counter);
14859 CHECK_EQ(0, promise_revoke_counter);
14861 // Add resolve handler (and default reject handler) to p0.
14862 CompileRun("var p1 = p0.then(function(){});");
14863 CHECK(GetPromise("p0")->HasHandler());
14864 CHECK(!GetPromise("p1")->HasHandler());
14865 CHECK_EQ(0, promise_reject_counter);
14866 CHECK_EQ(0, promise_revoke_counter);
14869 CompileRun("reject('ppp');");
14870 CHECK(GetPromise("p0")->HasHandler());
14871 CHECK(!GetPromise("p1")->HasHandler());
14872 CHECK_EQ(1, promise_reject_counter);
14873 CHECK_EQ(0, promise_revoke_counter);
14874 CHECK_EQ(v8::kPromiseRejectWithNoHandler, reject_event);
14875 CHECK(GetPromise("rejected")->Equals(GetPromise("p1")));
14876 CHECK(RejectValue()->Equals(v8_str("ppp")));
14878 // Reject p0 again. Callback is not triggered again.
14879 CompileRun("reject();");
14880 CHECK(GetPromise("p0")->HasHandler());
14881 CHECK(!GetPromise("p1")->HasHandler());
14882 CHECK_EQ(1, promise_reject_counter);
14883 CHECK_EQ(0, promise_revoke_counter);
14885 // Add resolve handler to p1.
14886 CompileRun("var p2 = p1.then(function(){});");
14887 CHECK(GetPromise("p0")->HasHandler());
14888 CHECK(GetPromise("p1")->HasHandler());
14889 CHECK(!GetPromise("p2")->HasHandler());
14890 CHECK_EQ(2, promise_reject_counter);
14891 CHECK_EQ(1, promise_revoke_counter);
14892 CHECK(GetPromise("rejected")->Equals(GetPromise("p2")));
14893 CHECK(RejectValue()->Equals(v8_str("ppp")));
14894 CHECK(GetPromise("revoked")->Equals(GetPromise("p1")));
14896 ResetPromiseStates();
14898 // Create promise q0.
14900 "var q0 = new Promise( \n"
14901 " function(res, rej) { \n"
14902 " reject = rej; \n"
14905 CHECK(!GetPromise("q0")->HasHandler());
14906 CHECK_EQ(0, promise_reject_counter);
14907 CHECK_EQ(0, promise_revoke_counter);
14909 // Add reject handler to q0.
14910 CompileRun("var q1 = q0.catch(function() {});");
14911 CHECK(GetPromise("q0")->HasHandler());
14912 CHECK(!GetPromise("q1")->HasHandler());
14913 CHECK_EQ(0, promise_reject_counter);
14914 CHECK_EQ(0, promise_revoke_counter);
14917 CompileRun("reject('qq')");
14918 CHECK(GetPromise("q0")->HasHandler());
14919 CHECK(!GetPromise("q1")->HasHandler());
14920 CHECK_EQ(0, promise_reject_counter);
14921 CHECK_EQ(0, promise_revoke_counter);
14923 // Add a new reject handler, which rejects by returning Promise.reject().
14924 // The returned promise q_ triggers a reject callback at first, only to
14925 // revoke it when returning it causes q2 to be rejected.
14928 "var q2 = q0.catch( \n"
14930 " q_ = Promise.reject('qqq'); \n"
14934 CHECK(GetPromise("q0")->HasHandler());
14935 CHECK(!GetPromise("q1")->HasHandler());
14936 CHECK(!GetPromise("q2")->HasHandler());
14937 CHECK(GetPromise("q_")->HasHandler());
14938 CHECK_EQ(2, promise_reject_counter);
14939 CHECK_EQ(1, promise_revoke_counter);
14940 CHECK(GetPromise("rejected")->Equals(GetPromise("q2")));
14941 CHECK(GetPromise("revoked")->Equals(GetPromise("q_")));
14942 CHECK(RejectValue()->Equals(v8_str("qqq")));
14944 // Add a reject handler to the resolved q1, which rejects by throwing.
14946 "var q3 = q1.then( \n"
14948 " throw 'qqqq'; \n"
14951 CHECK(GetPromise("q0")->HasHandler());
14952 CHECK(GetPromise("q1")->HasHandler());
14953 CHECK(!GetPromise("q2")->HasHandler());
14954 CHECK(!GetPromise("q3")->HasHandler());
14955 CHECK_EQ(3, promise_reject_counter);
14956 CHECK_EQ(1, promise_revoke_counter);
14957 CHECK(GetPromise("rejected")->Equals(GetPromise("q3")));
14958 CHECK(RejectValue()->Equals(v8_str("qqqq")));
14960 ResetPromiseStates();
14962 // Create promise r0, which has three handlers, two of which handle rejects.
14964 "var r0 = new Promise( \n"
14965 " function(res, rej) { \n"
14966 " reject = rej; \n"
14969 "var r1 = r0.catch(function() {}); \n"
14970 "var r2 = r0.then(function() {}); \n"
14971 "var r3 = r0.then(function() {}, \n"
14972 " function() {}); \n");
14973 CHECK(GetPromise("r0")->HasHandler());
14974 CHECK(!GetPromise("r1")->HasHandler());
14975 CHECK(!GetPromise("r2")->HasHandler());
14976 CHECK(!GetPromise("r3")->HasHandler());
14977 CHECK_EQ(0, promise_reject_counter);
14978 CHECK_EQ(0, promise_revoke_counter);
14981 CompileRun("reject('rrr')");
14982 CHECK(GetPromise("r0")->HasHandler());
14983 CHECK(!GetPromise("r1")->HasHandler());
14984 CHECK(!GetPromise("r2")->HasHandler());
14985 CHECK(!GetPromise("r3")->HasHandler());
14986 CHECK_EQ(1, promise_reject_counter);
14987 CHECK_EQ(0, promise_revoke_counter);
14988 CHECK(GetPromise("rejected")->Equals(GetPromise("r2")));
14989 CHECK(RejectValue()->Equals(v8_str("rrr")));
14991 // Add reject handler to r2.
14992 CompileRun("var r4 = r2.catch(function() {});");
14993 CHECK(GetPromise("r0")->HasHandler());
14994 CHECK(!GetPromise("r1")->HasHandler());
14995 CHECK(GetPromise("r2")->HasHandler());
14996 CHECK(!GetPromise("r3")->HasHandler());
14997 CHECK(!GetPromise("r4")->HasHandler());
14998 CHECK_EQ(1, promise_reject_counter);
14999 CHECK_EQ(1, promise_revoke_counter);
15000 CHECK(GetPromise("revoked")->Equals(GetPromise("r2")));
15001 CHECK(RejectValue()->Equals(v8_str("rrr")));
15003 // Add reject handlers to r4.
15004 CompileRun("var r5 = r4.then(function() {}, function() {});");
15005 CHECK(GetPromise("r0")->HasHandler());
15006 CHECK(!GetPromise("r1")->HasHandler());
15007 CHECK(GetPromise("r2")->HasHandler());
15008 CHECK(!GetPromise("r3")->HasHandler());
15009 CHECK(GetPromise("r4")->HasHandler());
15010 CHECK(!GetPromise("r5")->HasHandler());
15011 CHECK_EQ(1, promise_reject_counter);
15012 CHECK_EQ(1, promise_revoke_counter);
15014 ResetPromiseStates();
15016 // Create promise s0, which has three handlers, none of which handle rejects.
15018 "var s0 = new Promise( \n"
15019 " function(res, rej) { \n"
15020 " reject = rej; \n"
15023 "var s1 = s0.then(function() {}); \n"
15024 "var s2 = s0.then(function() {}); \n"
15025 "var s3 = s0.then(function() {}); \n");
15026 CHECK(GetPromise("s0")->HasHandler());
15027 CHECK(!GetPromise("s1")->HasHandler());
15028 CHECK(!GetPromise("s2")->HasHandler());
15029 CHECK(!GetPromise("s3")->HasHandler());
15030 CHECK_EQ(0, promise_reject_counter);
15031 CHECK_EQ(0, promise_revoke_counter);
15034 CompileRun("reject('sss')");
15035 CHECK(GetPromise("s0")->HasHandler());
15036 CHECK(!GetPromise("s1")->HasHandler());
15037 CHECK(!GetPromise("s2")->HasHandler());
15038 CHECK(!GetPromise("s3")->HasHandler());
15039 CHECK_EQ(3, promise_reject_counter);
15040 CHECK_EQ(0, promise_revoke_counter);
15041 CHECK(RejectValue()->Equals(v8_str("sss")));
15043 // Test stack frames.
15044 V8::SetCaptureStackTraceForUncaughtExceptions(true);
15046 ResetPromiseStates();
15048 // Create promise t0, which is rejected in the constructor with an error.
15049 CompileRunWithOrigin(
15050 "var t0 = new Promise( \n"
15051 " function(res, rej) { \n"
15052 " reference_error; \n"
15056 CHECK(!GetPromise("t0")->HasHandler());
15057 CHECK_EQ(1, promise_reject_counter);
15058 CHECK_EQ(0, promise_revoke_counter);
15059 CHECK_EQ(2, promise_reject_frame_count);
15060 CHECK_EQ(3, promise_reject_line_number);
15061 CHECK_EQ(5, promise_reject_column_number);
15062 CHECK_EQ(3, promise_reject_msg_line_number);
15063 CHECK_EQ(5, promise_reject_msg_column_number);
15065 ResetPromiseStates();
15067 // Create promise u0 and chain u1 to it, which is rejected via throw.
15068 CompileRunWithOrigin(
15069 "var u0 = Promise.resolve(); \n"
15070 "var u1 = u0.then( \n"
15072 " (function() { \n"
15073 " throw new Error(); \n"
15078 CHECK(GetPromise("u0")->HasHandler());
15079 CHECK(!GetPromise("u1")->HasHandler());
15080 CHECK_EQ(1, promise_reject_counter);
15081 CHECK_EQ(0, promise_revoke_counter);
15082 CHECK_EQ(2, promise_reject_frame_count);
15083 CHECK_EQ(5, promise_reject_line_number);
15084 CHECK_EQ(23, promise_reject_column_number);
15085 CHECK_EQ(5, promise_reject_msg_line_number);
15086 CHECK_EQ(23, promise_reject_msg_column_number);
15088 // Throw in u3, which handles u1's rejection.
15089 CompileRunWithOrigin(
15090 "function f() { \n"
15091 " return (function() { \n"
15092 " return new Error(); \n"
15095 "var u2 = Promise.reject(f()); \n"
15096 "var u3 = u1.catch( \n"
15102 CHECK(GetPromise("u0")->HasHandler());
15103 CHECK(GetPromise("u1")->HasHandler());
15104 CHECK(GetPromise("u2")->HasHandler());
15105 CHECK(!GetPromise("u3")->HasHandler());
15106 CHECK_EQ(3, promise_reject_counter);
15107 CHECK_EQ(2, promise_revoke_counter);
15108 CHECK_EQ(3, promise_reject_frame_count);
15109 CHECK_EQ(3, promise_reject_line_number);
15110 CHECK_EQ(12, promise_reject_column_number);
15111 CHECK_EQ(3, promise_reject_msg_line_number);
15112 CHECK_EQ(12, promise_reject_msg_column_number);
15114 ResetPromiseStates();
15116 // Create promise rejected promise v0, which is incorrectly handled by v1
15117 // via chaining cycle.
15118 CompileRunWithOrigin(
15119 "var v0 = Promise.reject(); \n"
15120 "var v1 = v0.catch( \n"
15126 CHECK(GetPromise("v0")->HasHandler());
15127 CHECK(!GetPromise("v1")->HasHandler());
15128 CHECK_EQ(2, promise_reject_counter);
15129 CHECK_EQ(1, promise_revoke_counter);
15130 CHECK_EQ(0, promise_reject_frame_count);
15131 CHECK_EQ(-1, promise_reject_line_number);
15132 CHECK_EQ(-1, promise_reject_column_number);
15134 ResetPromiseStates();
15136 // Create promise t1, which rejects by throwing syntax error from eval.
15137 CompileRunWithOrigin(
15138 "var t1 = new Promise( \n"
15139 " function(res, rej) { \n"
15140 " var content = '\\n\\\n"
15142 " eval(content); \n"
15146 CHECK(!GetPromise("t1")->HasHandler());
15147 CHECK_EQ(1, promise_reject_counter);
15148 CHECK_EQ(0, promise_revoke_counter);
15149 CHECK_EQ(2, promise_reject_frame_count);
15150 CHECK_EQ(5, promise_reject_line_number);
15151 CHECK_EQ(10, promise_reject_column_number);
15152 CHECK_EQ(2, promise_reject_msg_line_number);
15153 CHECK_EQ(7, promise_reject_msg_column_number);
15157 void AnalyzeStackOfEvalWithSourceURL(
15158 const v8::FunctionCallbackInfo<v8::Value>& args) {
15159 v8::HandleScope scope(args.GetIsolate());
15160 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15161 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15162 CHECK_EQ(5, stackTrace->GetFrameCount());
15163 v8::Handle<v8::String> url = v8_str("eval_url");
15164 for (int i = 0; i < 3; i++) {
15165 v8::Handle<v8::String> name =
15166 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15167 CHECK(!name.IsEmpty());
15168 CHECK(url->Equals(name));
15173 TEST(SourceURLInStackTrace) {
15174 v8::Isolate* isolate = CcTest::isolate();
15175 v8::HandleScope scope(isolate);
15176 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15177 templ->Set(v8_str("AnalyzeStackOfEvalWithSourceURL"),
15178 v8::FunctionTemplate::New(isolate,
15179 AnalyzeStackOfEvalWithSourceURL));
15180 LocalContext context(0, templ);
15182 const char *source =
15183 "function outer() {\n"
15184 "function bar() {\n"
15185 " AnalyzeStackOfEvalWithSourceURL();\n"
15187 "function foo() {\n"
15193 "eval('(' + outer +')()%s');";
15195 i::ScopedVector<char> code(1024);
15196 i::SNPrintF(code, source, "//# sourceURL=eval_url");
15197 CHECK(CompileRun(code.start())->IsUndefined());
15198 i::SNPrintF(code, source, "//@ sourceURL=eval_url");
15199 CHECK(CompileRun(code.start())->IsUndefined());
15203 static int scriptIdInStack[2];
15205 void AnalyzeScriptIdInStack(
15206 const v8::FunctionCallbackInfo<v8::Value>& args) {
15207 v8::HandleScope scope(args.GetIsolate());
15208 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15209 args.GetIsolate(), 10, v8::StackTrace::kScriptId);
15210 CHECK_EQ(2, stackTrace->GetFrameCount());
15211 for (int i = 0; i < 2; i++) {
15212 scriptIdInStack[i] = stackTrace->GetFrame(i)->GetScriptId();
15217 TEST(ScriptIdInStackTrace) {
15218 v8::Isolate* isolate = CcTest::isolate();
15219 v8::HandleScope scope(isolate);
15220 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15221 templ->Set(v8_str("AnalyzeScriptIdInStack"),
15222 v8::FunctionTemplate::New(isolate, AnalyzeScriptIdInStack));
15223 LocalContext context(0, templ);
15225 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
15227 "function foo() {\n"
15228 " AnalyzeScriptIdInStack();"
15231 v8::Local<v8::Script> script = CompileWithOrigin(scriptSource, "test");
15233 for (int i = 0; i < 2; i++) {
15234 CHECK(scriptIdInStack[i] != v8::Message::kNoScriptIdInfo);
15235 CHECK_EQ(scriptIdInStack[i], script->GetUnboundScript()->GetId());
15240 void AnalyzeStackOfInlineScriptWithSourceURL(
15241 const v8::FunctionCallbackInfo<v8::Value>& args) {
15242 v8::HandleScope scope(args.GetIsolate());
15243 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15244 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15245 CHECK_EQ(4, stackTrace->GetFrameCount());
15246 v8::Handle<v8::String> url = v8_str("source_url");
15247 for (int i = 0; i < 3; i++) {
15248 v8::Handle<v8::String> name =
15249 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15250 CHECK(!name.IsEmpty());
15251 CHECK(url->Equals(name));
15256 TEST(InlineScriptWithSourceURLInStackTrace) {
15257 v8::Isolate* isolate = CcTest::isolate();
15258 v8::HandleScope scope(isolate);
15259 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15260 templ->Set(v8_str("AnalyzeStackOfInlineScriptWithSourceURL"),
15261 v8::FunctionTemplate::New(
15262 CcTest::isolate(), AnalyzeStackOfInlineScriptWithSourceURL));
15263 LocalContext context(0, templ);
15265 const char *source =
15266 "function outer() {\n"
15267 "function bar() {\n"
15268 " AnalyzeStackOfInlineScriptWithSourceURL();\n"
15270 "function foo() {\n"
15278 i::ScopedVector<char> code(1024);
15279 i::SNPrintF(code, source, "//# sourceURL=source_url");
15280 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15281 i::SNPrintF(code, source, "//@ sourceURL=source_url");
15282 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined());
15286 void AnalyzeStackOfDynamicScriptWithSourceURL(
15287 const v8::FunctionCallbackInfo<v8::Value>& args) {
15288 v8::HandleScope scope(args.GetIsolate());
15289 v8::Handle<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(
15290 args.GetIsolate(), 10, v8::StackTrace::kDetailed);
15291 CHECK_EQ(4, stackTrace->GetFrameCount());
15292 v8::Handle<v8::String> url = v8_str("source_url");
15293 for (int i = 0; i < 3; i++) {
15294 v8::Handle<v8::String> name =
15295 stackTrace->GetFrame(i)->GetScriptNameOrSourceURL();
15296 CHECK(!name.IsEmpty());
15297 CHECK(url->Equals(name));
15302 TEST(DynamicWithSourceURLInStackTrace) {
15303 v8::Isolate* isolate = CcTest::isolate();
15304 v8::HandleScope scope(isolate);
15305 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
15306 templ->Set(v8_str("AnalyzeStackOfDynamicScriptWithSourceURL"),
15307 v8::FunctionTemplate::New(
15308 CcTest::isolate(), AnalyzeStackOfDynamicScriptWithSourceURL));
15309 LocalContext context(0, templ);
15311 const char *source =
15312 "function outer() {\n"
15313 "function bar() {\n"
15314 " AnalyzeStackOfDynamicScriptWithSourceURL();\n"
15316 "function foo() {\n"
15324 i::ScopedVector<char> code(1024);
15325 i::SNPrintF(code, source, "//# sourceURL=source_url");
15326 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15327 i::SNPrintF(code, source, "//@ sourceURL=source_url");
15328 CHECK(CompileRunWithOrigin(code.start(), "url", 0, 0)->IsUndefined());
15332 TEST(DynamicWithSourceURLInStackTraceString) {
15333 LocalContext context;
15334 v8::HandleScope scope(context->GetIsolate());
15336 const char *source =
15337 "function outer() {\n"
15338 " function foo() {\n"
15345 i::ScopedVector<char> code(1024);
15346 i::SNPrintF(code, source, "//# sourceURL=source_url");
15347 v8::TryCatch try_catch(context->GetIsolate());
15348 CompileRunWithOrigin(code.start(), "", 0, 0);
15349 CHECK(try_catch.HasCaught());
15350 v8::String::Utf8Value stack(try_catch.StackTrace());
15351 CHECK(strstr(*stack, "at foo (source_url:3:5)") != NULL);
15355 TEST(EvalWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15356 LocalContext context;
15357 v8::HandleScope scope(context->GetIsolate());
15359 const char *source =
15360 "function outer() {\n"
15361 " var scriptContents = \"function foo() { FAIL.FAIL; }\\\n"
15362 " //# sourceURL=source_url\";\n"
15363 " eval(scriptContents);\n"
15366 "//# sourceURL=outer_url";
15368 v8::TryCatch try_catch(context->GetIsolate());
15369 CompileRun(source);
15370 CHECK(try_catch.HasCaught());
15372 Local<v8::Message> message = try_catch.Message();
15373 Handle<Value> sourceURL =
15374 message->GetScriptOrigin().ResourceName();
15375 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15379 TEST(RecursionWithSourceURLInMessageScriptResourceNameOrSourceURL) {
15380 LocalContext context;
15381 v8::HandleScope scope(context->GetIsolate());
15383 const char *source =
15384 "function outer() {\n"
15385 " var scriptContents = \"function boo(){ boo(); }\\\n"
15386 " //# sourceURL=source_url\";\n"
15387 " eval(scriptContents);\n"
15390 "//# sourceURL=outer_url";
15392 v8::TryCatch try_catch(context->GetIsolate());
15393 CompileRun(source);
15394 CHECK(try_catch.HasCaught());
15396 Local<v8::Message> message = try_catch.Message();
15397 Handle<Value> sourceURL =
15398 message->GetScriptOrigin().ResourceName();
15399 CHECK_EQ(0, strcmp(*v8::String::Utf8Value(sourceURL), "source_url"));
15403 static void CreateGarbageInOldSpace() {
15404 i::Factory* factory = CcTest::i_isolate()->factory();
15405 v8::HandleScope scope(CcTest::isolate());
15406 i::AlwaysAllocateScope always_allocate(CcTest::i_isolate());
15407 for (int i = 0; i < 1000; i++) {
15408 factory->NewFixedArray(1000, i::TENURED);
15413 // Test that idle notification can be handled and eventually collects garbage.
15414 TEST(TestIdleNotification) {
15415 if (!i::FLAG_incremental_marking) return;
15416 const intptr_t MB = 1024 * 1024;
15417 const double IdlePauseInSeconds = 1.0;
15419 v8::HandleScope scope(env->GetIsolate());
15420 intptr_t initial_size = CcTest::heap()->SizeOfObjects();
15421 CreateGarbageInOldSpace();
15422 intptr_t size_with_garbage = CcTest::heap()->SizeOfObjects();
15423 CHECK_GT(size_with_garbage, initial_size + MB);
15424 bool finished = false;
15425 for (int i = 0; i < 200 && !finished; i++) {
15426 if (i < 10 && CcTest::heap()->incremental_marking()->IsStopped()) {
15427 CcTest::heap()->StartIdleIncrementalMarking();
15429 finished = env->GetIsolate()->IdleNotificationDeadline(
15430 (v8::base::TimeTicks::HighResolutionNow().ToInternalValue() /
15431 static_cast<double>(v8::base::Time::kMicrosecondsPerSecond)) +
15432 IdlePauseInSeconds);
15433 if (CcTest::heap()->mark_compact_collector()->sweeping_in_progress()) {
15434 CcTest::heap()->mark_compact_collector()->EnsureSweepingCompleted();
15437 intptr_t final_size = CcTest::heap()->SizeOfObjects();
15439 CHECK_LT(final_size, initial_size + 1);
15443 TEST(Regress2333) {
15445 for (int i = 0; i < 3; i++) {
15446 CcTest::heap()->CollectGarbage(i::NEW_SPACE);
15450 static uint32_t* stack_limit;
15452 static void GetStackLimitCallback(
15453 const v8::FunctionCallbackInfo<v8::Value>& args) {
15454 stack_limit = reinterpret_cast<uint32_t*>(
15455 CcTest::i_isolate()->stack_guard()->real_climit());
15459 // Uses the address of a local variable to determine the stack top now.
15460 // Given a size, returns an address that is that far from the current
15462 static uint32_t* ComputeStackLimit(uint32_t size) {
15463 uint32_t* answer = &size - (size / sizeof(size));
15464 // If the size is very large and the stack is very near the bottom of
15465 // memory then the calculation above may wrap around and give an address
15466 // that is above the (downwards-growing) stack. In that case we return
15467 // a very low address.
15468 if (answer > &size) return reinterpret_cast<uint32_t*>(sizeof(size));
15473 // We need at least 165kB for an x64 debug build with clang and ASAN.
15474 static const int stack_breathing_room = 256 * i::KB;
15477 TEST(SetStackLimit) {
15478 uint32_t* set_limit = ComputeStackLimit(stack_breathing_room);
15480 // Set stack limit.
15481 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
15483 // Execute a script.
15485 v8::HandleScope scope(env->GetIsolate());
15486 Local<v8::FunctionTemplate> fun_templ =
15487 v8::FunctionTemplate::New(env->GetIsolate(), GetStackLimitCallback);
15488 Local<Function> fun = fun_templ->GetFunction();
15489 env->Global()->Set(v8_str("get_stack_limit"), fun);
15490 CompileRun("get_stack_limit();");
15492 CHECK(stack_limit == set_limit);
15496 TEST(SetStackLimitInThread) {
15497 uint32_t* set_limit;
15499 v8::Locker locker(CcTest::isolate());
15500 set_limit = ComputeStackLimit(stack_breathing_room);
15502 // Set stack limit.
15503 CcTest::isolate()->SetStackLimit(reinterpret_cast<uintptr_t>(set_limit));
15505 // Execute a script.
15506 v8::HandleScope scope(CcTest::isolate());
15508 Local<v8::FunctionTemplate> fun_templ =
15509 v8::FunctionTemplate::New(CcTest::isolate(), GetStackLimitCallback);
15510 Local<Function> fun = fun_templ->GetFunction();
15511 env->Global()->Set(v8_str("get_stack_limit"), fun);
15512 CompileRun("get_stack_limit();");
15514 CHECK(stack_limit == set_limit);
15517 v8::Locker locker(CcTest::isolate());
15518 CHECK(stack_limit == set_limit);
15523 THREADED_TEST(GetHeapStatistics) {
15525 v8::HandleScope scope(c1->GetIsolate());
15526 v8::HeapStatistics heap_statistics;
15527 CHECK_EQ(0u, heap_statistics.total_heap_size());
15528 CHECK_EQ(0u, heap_statistics.used_heap_size());
15529 c1->GetIsolate()->GetHeapStatistics(&heap_statistics);
15530 CHECK_NE(static_cast<int>(heap_statistics.total_heap_size()), 0);
15531 CHECK_NE(static_cast<int>(heap_statistics.used_heap_size()), 0);
15535 class VisitorImpl : public v8::ExternalResourceVisitor {
15537 explicit VisitorImpl(TestResource** resource) {
15538 for (int i = 0; i < 4; i++) {
15539 resource_[i] = resource[i];
15540 found_resource_[i] = false;
15543 virtual ~VisitorImpl() {}
15544 virtual void VisitExternalString(v8::Handle<v8::String> string) {
15545 if (!string->IsExternal()) {
15546 CHECK(string->IsExternalOneByte());
15549 v8::String::ExternalStringResource* resource =
15550 string->GetExternalStringResource();
15552 for (int i = 0; i < 4; i++) {
15553 if (resource_[i] == resource) {
15554 CHECK(!found_resource_[i]);
15555 found_resource_[i] = true;
15559 void CheckVisitedResources() {
15560 for (int i = 0; i < 4; i++) {
15561 CHECK(found_resource_[i]);
15566 v8::String::ExternalStringResource* resource_[4];
15567 bool found_resource_[4];
15571 TEST(ExternalizeOldSpaceTwoByteCons) {
15572 v8::Isolate* isolate = CcTest::isolate();
15574 v8::HandleScope scope(isolate);
15575 v8::Local<v8::String> cons =
15576 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
15577 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
15578 CcTest::heap()->CollectAllAvailableGarbage();
15579 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
15581 TestResource* resource = new TestResource(
15582 AsciiToTwoByteString("Romeo Montague Juliet Capulet"));
15583 cons->MakeExternal(resource);
15585 CHECK(cons->IsExternal());
15586 CHECK_EQ(resource, cons->GetExternalStringResource());
15587 String::Encoding encoding;
15588 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
15589 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding);
15593 TEST(ExternalizeOldSpaceOneByteCons) {
15594 v8::Isolate* isolate = CcTest::isolate();
15596 v8::HandleScope scope(isolate);
15597 v8::Local<v8::String> cons =
15598 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(isolate);
15599 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString());
15600 CcTest::heap()->CollectAllAvailableGarbage();
15601 CHECK(CcTest::heap()->old_space()->Contains(*v8::Utils::OpenHandle(*cons)));
15603 TestOneByteResource* resource =
15604 new TestOneByteResource(i::StrDup("Romeo Montague Juliet Capulet"));
15605 cons->MakeExternal(resource);
15607 CHECK(cons->IsExternalOneByte());
15608 CHECK_EQ(resource, cons->GetExternalOneByteStringResource());
15609 String::Encoding encoding;
15610 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding));
15611 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding);
15615 TEST(VisitExternalStrings) {
15616 v8::Isolate* isolate = CcTest::isolate();
15618 v8::HandleScope scope(isolate);
15619 const char* string = "Some string";
15620 uint16_t* two_byte_string = AsciiToTwoByteString(string);
15621 TestResource* resource[4];
15622 resource[0] = new TestResource(two_byte_string);
15623 v8::Local<v8::String> string0 =
15624 v8::String::NewExternal(env->GetIsolate(), resource[0]);
15625 resource[1] = new TestResource(two_byte_string, NULL, false);
15626 v8::Local<v8::String> string1 =
15627 v8::String::NewExternal(env->GetIsolate(), resource[1]);
15629 // Externalized symbol.
15630 resource[2] = new TestResource(two_byte_string, NULL, false);
15631 v8::Local<v8::String> string2 = v8::String::NewFromUtf8(
15632 env->GetIsolate(), string, v8::String::kInternalizedString);
15633 CHECK(string2->MakeExternal(resource[2]));
15635 // Symbolized External.
15636 resource[3] = new TestResource(AsciiToTwoByteString("Some other string"));
15637 v8::Local<v8::String> string3 =
15638 v8::String::NewExternal(env->GetIsolate(), resource[3]);
15639 CcTest::heap()->CollectAllAvailableGarbage(); // Tenure string.
15640 // Turn into a symbol.
15641 i::Handle<i::String> string3_i = v8::Utils::OpenHandle(*string3);
15642 CHECK(!CcTest::i_isolate()->factory()->InternalizeString(
15643 string3_i).is_null());
15644 CHECK(string3_i->IsInternalizedString());
15646 // We need to add usages for string* to avoid warnings in GCC 4.7
15647 CHECK(string0->IsExternal());
15648 CHECK(string1->IsExternal());
15649 CHECK(string2->IsExternal());
15650 CHECK(string3->IsExternal());
15652 VisitorImpl visitor(resource);
15653 v8::V8::VisitExternalResources(&visitor);
15654 visitor.CheckVisitedResources();
15658 TEST(ExternalStringCollectedAtTearDown) {
15660 v8::Isolate::CreateParams create_params;
15661 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
15662 v8::Isolate* isolate = v8::Isolate::New(create_params);
15663 { v8::Isolate::Scope isolate_scope(isolate);
15664 v8::HandleScope handle_scope(isolate);
15665 const char* s = "One string to test them all, one string to find them.";
15666 TestOneByteResource* inscription =
15667 new TestOneByteResource(i::StrDup(s), &destroyed);
15668 v8::Local<v8::String> ring = v8::String::NewExternal(isolate, inscription);
15669 // Ring is still alive. Orcs are roaming freely across our lands.
15670 CHECK_EQ(0, destroyed);
15674 isolate->Dispose();
15675 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
15676 CHECK_EQ(1, destroyed);
15680 TEST(ExternalInternalizedStringCollectedAtTearDown) {
15682 v8::Isolate::CreateParams create_params;
15683 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
15684 v8::Isolate* isolate = v8::Isolate::New(create_params);
15685 { v8::Isolate::Scope isolate_scope(isolate);
15686 LocalContext env(isolate);
15687 v8::HandleScope handle_scope(isolate);
15688 CompileRun("var ring = 'One string to test them all';");
15689 const char* s = "One string to test them all";
15690 TestOneByteResource* inscription =
15691 new TestOneByteResource(i::StrDup(s), &destroyed);
15692 v8::Local<v8::String> ring = CompileRun("ring")->ToString(isolate);
15693 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
15694 ring->MakeExternal(inscription);
15695 // Ring is still alive. Orcs are roaming freely across our lands.
15696 CHECK_EQ(0, destroyed);
15700 isolate->Dispose();
15701 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
15702 CHECK_EQ(1, destroyed);
15706 TEST(ExternalInternalizedStringCollectedAtGC) {
15708 { LocalContext env;
15709 v8::HandleScope handle_scope(env->GetIsolate());
15710 CompileRun("var ring = 'One string to test them all';");
15711 const char* s = "One string to test them all";
15712 TestOneByteResource* inscription =
15713 new TestOneByteResource(i::StrDup(s), &destroyed);
15714 v8::Local<v8::String> ring = CompileRun("ring").As<v8::String>();
15715 CHECK(v8::Utils::OpenHandle(*ring)->IsInternalizedString());
15716 ring->MakeExternal(inscription);
15717 // Ring is still alive. Orcs are roaming freely across our lands.
15718 CHECK_EQ(0, destroyed);
15722 // Garbage collector deals swift blows to evil.
15723 CcTest::i_isolate()->compilation_cache()->Clear();
15724 CcTest::heap()->CollectAllAvailableGarbage();
15726 // Ring has been destroyed. Free Peoples of Middle-earth Rejoice.
15727 CHECK_EQ(1, destroyed);
15731 static double DoubleFromBits(uint64_t value) {
15733 i::MemCopy(&target, &value, sizeof(target));
15738 static uint64_t DoubleToBits(double value) {
15740 i::MemCopy(&target, &value, sizeof(target));
15745 static double DoubleToDateTime(double input) {
15746 double date_limit = 864e13;
15747 if (std::isnan(input) || input < -date_limit || input > date_limit) {
15748 return std::numeric_limits<double>::quiet_NaN();
15750 return (input < 0) ? -(std::floor(-input)) : std::floor(input);
15754 // We don't have a consistent way to write 64-bit constants syntactically, so we
15755 // split them into two 32-bit constants and combine them programmatically.
15756 static double DoubleFromBits(uint32_t high_bits, uint32_t low_bits) {
15757 return DoubleFromBits((static_cast<uint64_t>(high_bits) << 32) | low_bits);
15761 THREADED_TEST(QuietSignalingNaNs) {
15762 LocalContext context;
15763 v8::Isolate* isolate = context->GetIsolate();
15764 v8::HandleScope scope(isolate);
15765 v8::TryCatch try_catch(isolate);
15767 // Special double values.
15768 double snan = DoubleFromBits(0x7ff00000, 0x00000001);
15769 double qnan = DoubleFromBits(0x7ff80000, 0x00000000);
15770 double infinity = DoubleFromBits(0x7ff00000, 0x00000000);
15771 double max_normal = DoubleFromBits(0x7fefffff, 0xffffffffu);
15772 double min_normal = DoubleFromBits(0x00100000, 0x00000000);
15773 double max_denormal = DoubleFromBits(0x000fffff, 0xffffffffu);
15774 double min_denormal = DoubleFromBits(0x00000000, 0x00000001);
15776 // Date values are capped at +/-100000000 days (times 864e5 ms per day)
15777 // on either side of the epoch.
15778 double date_limit = 864e13;
15780 double test_values[] = {
15802 int num_test_values = 20;
15804 for (int i = 0; i < num_test_values; i++) {
15805 double test_value = test_values[i];
15807 // Check that Number::New preserves non-NaNs and quiets SNaNs.
15808 v8::Handle<v8::Value> number = v8::Number::New(isolate, test_value);
15809 double stored_number = number->NumberValue();
15810 if (!std::isnan(test_value)) {
15811 CHECK_EQ(test_value, stored_number);
15813 uint64_t stored_bits = DoubleToBits(stored_number);
15814 // Check if quiet nan (bits 51..62 all set).
15815 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
15816 !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
15817 // Most significant fraction bit for quiet nan is set to 0
15818 // on MIPS architecture. Allowed by IEEE-754.
15819 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15821 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
15825 // Check that Date::New preserves non-NaNs in the date range and
15827 v8::Handle<v8::Value> date =
15828 v8::Date::New(isolate, test_value);
15829 double expected_stored_date = DoubleToDateTime(test_value);
15830 double stored_date = date->NumberValue();
15831 if (!std::isnan(expected_stored_date)) {
15832 CHECK_EQ(expected_stored_date, stored_date);
15834 uint64_t stored_bits = DoubleToBits(stored_date);
15835 // Check if quiet nan (bits 51..62 all set).
15836 #if (defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64)) && \
15837 !defined(_MIPS_ARCH_MIPS64R6) && !defined(USE_SIMULATOR)
15838 // Most significant fraction bit for quiet nan is set to 0
15839 // on MIPS architecture. Allowed by IEEE-754.
15840 CHECK_EQ(0xffe, static_cast<int>((stored_bits >> 51) & 0xfff));
15842 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff));
15849 static void SpaghettiIncident(
15850 const v8::FunctionCallbackInfo<v8::Value>& args) {
15851 v8::HandleScope scope(args.GetIsolate());
15852 v8::TryCatch tc(args.GetIsolate());
15853 v8::Handle<v8::String> str(args[0]->ToString(args.GetIsolate()));
15855 if (tc.HasCaught())
15860 // Test that an exception can be propagated down through a spaghetti
15861 // stack using ReThrow.
15862 THREADED_TEST(SpaghettiStackReThrow) {
15863 v8::Isolate* isolate = CcTest::isolate();
15864 v8::HandleScope scope(isolate);
15865 LocalContext context;
15866 context->Global()->Set(
15867 v8::String::NewFromUtf8(isolate, "s"),
15868 v8::FunctionTemplate::New(isolate, SpaghettiIncident)->GetFunction());
15869 v8::TryCatch try_catch(isolate);
15873 " toString: function () {"
15883 CHECK(try_catch.HasCaught());
15884 v8::String::Utf8Value value(try_catch.Exception());
15885 CHECK_EQ(0, strcmp(*value, "Hey!"));
15890 v8::V8::Initialize();
15891 v8::Isolate* isolate = CcTest::isolate();
15892 i::FLAG_retain_maps_for_n_gc = 0;
15893 v8::HandleScope scope(isolate);
15894 v8::Local<Context> other_context;
15897 // Create a context used to keep the code from aging in the compilation
15899 other_context = Context::New(isolate);
15901 // Context-dependent context data creates reference from the compilation
15902 // cache to the global object.
15903 const char* source_simple = "1";
15905 v8::HandleScope scope(isolate);
15906 v8::Local<Context> context = Context::New(isolate);
15909 Local<v8::String> obj = v8::String::NewFromUtf8(isolate, "");
15910 context->SetEmbedderData(0, obj);
15911 CompileRun(source_simple);
15914 isolate->ContextDisposedNotification();
15915 for (gc_count = 1; gc_count < 10; gc_count++) {
15916 other_context->Enter();
15917 CompileRun(source_simple);
15918 other_context->Exit();
15919 CcTest::heap()->CollectAllGarbage();
15920 if (GetGlobalObjectsCount() == 1) break;
15922 CHECK_GE(2, gc_count);
15923 CHECK_EQ(1, GetGlobalObjectsCount());
15925 // Eval in a function creates reference from the compilation cache to the
15927 const char* source_eval = "function f(){eval('1')}; f()";
15929 v8::HandleScope scope(isolate);
15930 v8::Local<Context> context = Context::New(isolate);
15933 CompileRun(source_eval);
15936 isolate->ContextDisposedNotification();
15937 for (gc_count = 1; gc_count < 10; gc_count++) {
15938 other_context->Enter();
15939 CompileRun(source_eval);
15940 other_context->Exit();
15941 CcTest::heap()->CollectAllGarbage();
15942 if (GetGlobalObjectsCount() == 1) break;
15944 CHECK_GE(2, gc_count);
15945 CHECK_EQ(1, GetGlobalObjectsCount());
15947 // Looking up the line number for an exception creates reference from the
15948 // compilation cache to the global object.
15949 const char* source_exception = "function f(){throw 1;} f()";
15951 v8::HandleScope scope(isolate);
15952 v8::Local<Context> context = Context::New(isolate);
15955 v8::TryCatch try_catch(isolate);
15956 CompileRun(source_exception);
15957 CHECK(try_catch.HasCaught());
15958 v8::Handle<v8::Message> message = try_catch.Message();
15959 CHECK(!message.IsEmpty());
15960 CHECK_EQ(1, message->GetLineNumber());
15963 isolate->ContextDisposedNotification();
15964 for (gc_count = 1; gc_count < 10; gc_count++) {
15965 other_context->Enter();
15966 CompileRun(source_exception);
15967 other_context->Exit();
15968 CcTest::heap()->CollectAllGarbage();
15969 if (GetGlobalObjectsCount() == 1) break;
15971 CHECK_GE(2, gc_count);
15972 CHECK_EQ(1, GetGlobalObjectsCount());
15974 isolate->ContextDisposedNotification();
15978 THREADED_TEST(ScriptOrigin) {
15980 v8::HandleScope scope(env->GetIsolate());
15981 v8::ScriptOrigin origin = v8::ScriptOrigin(
15982 v8::String::NewFromUtf8(env->GetIsolate(), "test"),
15983 v8::Integer::New(env->GetIsolate(), 1),
15984 v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()),
15985 v8::Handle<v8::Integer>(), v8::True(env->GetIsolate()),
15986 v8::String::NewFromUtf8(env->GetIsolate(), "http://sourceMapUrl"),
15987 v8::True(env->GetIsolate()));
15988 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
15989 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
15990 v8::Script::Compile(script, &origin)->Run();
15991 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
15992 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
15993 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
15994 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
15996 v8::ScriptOrigin script_origin_f = f->GetScriptOrigin();
15997 CHECK_EQ(0, strcmp("test",
15998 *v8::String::Utf8Value(script_origin_f.ResourceName())));
15999 CHECK_EQ(1, script_origin_f.ResourceLineOffset()->Int32Value());
16000 CHECK(script_origin_f.Options().IsSharedCrossOrigin());
16001 CHECK(script_origin_f.Options().IsEmbedderDebugScript());
16002 CHECK(script_origin_f.Options().IsOpaque());
16003 printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined());
16005 CHECK_EQ(0, strcmp("http://sourceMapUrl",
16006 *v8::String::Utf8Value(script_origin_f.SourceMapUrl())));
16008 v8::ScriptOrigin script_origin_g = g->GetScriptOrigin();
16009 CHECK_EQ(0, strcmp("test",
16010 *v8::String::Utf8Value(script_origin_g.ResourceName())));
16011 CHECK_EQ(1, script_origin_g.ResourceLineOffset()->Int32Value());
16012 CHECK(script_origin_g.Options().IsSharedCrossOrigin());
16013 CHECK(script_origin_g.Options().IsEmbedderDebugScript());
16014 CHECK(script_origin_g.Options().IsOpaque());
16015 CHECK_EQ(0, strcmp("http://sourceMapUrl",
16016 *v8::String::Utf8Value(script_origin_g.SourceMapUrl())));
16020 THREADED_TEST(FunctionGetInferredName) {
16022 v8::HandleScope scope(env->GetIsolate());
16023 v8::ScriptOrigin origin =
16024 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16025 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16027 "var foo = { bar : { baz : function() {}}}; var f = foo.bar.baz;");
16028 v8::Script::Compile(script, &origin)->Run();
16029 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16030 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16032 strcmp("foo.bar.baz", *v8::String::Utf8Value(f->GetInferredName())));
16036 THREADED_TEST(FunctionGetDisplayName) {
16038 v8::HandleScope scope(env->GetIsolate());
16039 const char* code = "var error = false;"
16040 "function a() { this.x = 1; };"
16041 "a.displayName = 'display_a';"
16042 "var b = (function() {"
16043 " var f = function() { this.x = 2; };"
16044 " f.displayName = 'display_b';"
16047 "var c = function() {};"
16048 "c.__defineGetter__('displayName', function() {"
16050 " throw new Error();"
16053 "d.__defineGetter__('displayName', function() {"
16055 " return 'wrong_display_name';"
16058 "e.displayName = 'wrong_display_name';"
16059 "e.__defineSetter__('displayName', function() {"
16061 " throw new Error();"
16064 "f.displayName = { 'foo': 6, toString: function() {"
16066 " return 'wrong_display_name';"
16068 "var g = function() {"
16069 " arguments.callee.displayName = 'set_in_runtime';"
16072 v8::ScriptOrigin origin =
16073 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16074 v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), code), &origin)
16076 v8::Local<v8::Value> error =
16077 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "error"));
16078 v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
16079 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "a")));
16080 v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
16081 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "b")));
16082 v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
16083 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "c")));
16084 v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
16085 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "d")));
16086 v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
16087 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "e")));
16088 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16089 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16090 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16091 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16092 CHECK_EQ(false, error->BooleanValue());
16093 CHECK_EQ(0, strcmp("display_a", *v8::String::Utf8Value(a->GetDisplayName())));
16094 CHECK_EQ(0, strcmp("display_b", *v8::String::Utf8Value(b->GetDisplayName())));
16095 CHECK(c->GetDisplayName()->IsUndefined());
16096 CHECK(d->GetDisplayName()->IsUndefined());
16097 CHECK(e->GetDisplayName()->IsUndefined());
16098 CHECK(f->GetDisplayName()->IsUndefined());
16100 0, strcmp("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName())));
16104 THREADED_TEST(ScriptLineNumber) {
16106 v8::HandleScope scope(env->GetIsolate());
16107 v8::ScriptOrigin origin =
16108 v8::ScriptOrigin(v8::String::NewFromUtf8(env->GetIsolate(), "test"));
16109 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16110 env->GetIsolate(), "function f() {}\n\nfunction g() {}");
16111 v8::Script::Compile(script, &origin)->Run();
16112 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16113 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16114 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16115 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16116 CHECK_EQ(0, f->GetScriptLineNumber());
16117 CHECK_EQ(2, g->GetScriptLineNumber());
16121 THREADED_TEST(ScriptColumnNumber) {
16123 v8::Isolate* isolate = env->GetIsolate();
16124 v8::HandleScope scope(isolate);
16125 v8::ScriptOrigin origin =
16126 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16127 v8::Integer::New(isolate, 3),
16128 v8::Integer::New(isolate, 2));
16129 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16130 isolate, "function foo() {}\n\n function bar() {}");
16131 v8::Script::Compile(script, &origin)->Run();
16132 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16133 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16134 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16135 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16136 CHECK_EQ(14, foo->GetScriptColumnNumber());
16137 CHECK_EQ(17, bar->GetScriptColumnNumber());
16141 THREADED_TEST(FunctionIsBuiltin) {
16143 v8::Isolate* isolate = env->GetIsolate();
16144 v8::HandleScope scope(isolate);
16145 v8::Local<v8::Function> f;
16146 f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
16147 CHECK(f->IsBuiltin());
16148 f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
16149 CHECK(f->IsBuiltin());
16150 f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
16151 CHECK(f->IsBuiltin());
16152 f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
16153 CHECK(f->IsBuiltin());
16154 f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
16155 CHECK(!f->IsBuiltin());
16159 THREADED_TEST(FunctionGetScriptId) {
16161 v8::Isolate* isolate = env->GetIsolate();
16162 v8::HandleScope scope(isolate);
16163 v8::ScriptOrigin origin =
16164 v8::ScriptOrigin(v8::String::NewFromUtf8(isolate, "test"),
16165 v8::Integer::New(isolate, 3),
16166 v8::Integer::New(isolate, 2));
16167 v8::Handle<v8::String> scriptSource = v8::String::NewFromUtf8(
16168 isolate, "function foo() {}\n\n function bar() {}");
16169 v8::Local<v8::Script> script(v8::Script::Compile(scriptSource, &origin));
16171 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
16172 env->Global()->Get(v8::String::NewFromUtf8(isolate, "foo")));
16173 v8::Local<v8::Function> bar = v8::Local<v8::Function>::Cast(
16174 env->Global()->Get(v8::String::NewFromUtf8(isolate, "bar")));
16175 CHECK_EQ(script->GetUnboundScript()->GetId(), foo->ScriptId());
16176 CHECK_EQ(script->GetUnboundScript()->GetId(), bar->ScriptId());
16180 THREADED_TEST(FunctionGetBoundFunction) {
16182 v8::HandleScope scope(env->GetIsolate());
16183 v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::NewFromUtf8(
16184 env->GetIsolate(), "test"));
16185 v8::Handle<v8::String> script = v8::String::NewFromUtf8(
16187 "var a = new Object();\n"
16189 "function f () { return this.x };\n"
16190 "var g = f.bind(a);\n"
16192 v8::Script::Compile(script, &origin)->Run();
16193 v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
16194 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
16195 v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
16196 env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "g")));
16197 CHECK(g->GetBoundFunction()->IsFunction());
16198 Local<v8::Function> original_function = Local<v8::Function>::Cast(
16199 g->GetBoundFunction());
16200 CHECK(f->GetName()->Equals(original_function->GetName()));
16201 CHECK_EQ(f->GetScriptLineNumber(), original_function->GetScriptLineNumber());
16202 CHECK_EQ(f->GetScriptColumnNumber(),
16203 original_function->GetScriptColumnNumber());
16207 static void GetterWhichReturns42(
16208 Local<String> name,
16209 const v8::PropertyCallbackInfo<v8::Value>& info) {
16210 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16211 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16212 info.GetReturnValue().Set(v8_num(42));
16216 static void SetterWhichSetsYOnThisTo23(
16217 Local<String> name,
16218 Local<Value> value,
16219 const v8::PropertyCallbackInfo<void>& info) {
16220 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16221 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16222 Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16226 void FooGetInterceptor(Local<Name> name,
16227 const v8::PropertyCallbackInfo<v8::Value>& info) {
16228 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16229 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16230 if (!name->Equals(v8_str("foo"))) return;
16231 info.GetReturnValue().Set(v8_num(42));
16235 void FooSetInterceptor(Local<Name> name, Local<Value> value,
16236 const v8::PropertyCallbackInfo<v8::Value>& info) {
16237 CHECK(v8::Utils::OpenHandle(*info.This())->IsJSObject());
16238 CHECK(v8::Utils::OpenHandle(*info.Holder())->IsJSObject());
16239 if (!name->Equals(v8_str("foo"))) return;
16240 Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16241 info.GetReturnValue().Set(v8_num(23));
16245 TEST(SetterOnConstructorPrototype) {
16246 v8::Isolate* isolate = CcTest::isolate();
16247 v8::HandleScope scope(isolate);
16248 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16249 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16250 SetterWhichSetsYOnThisTo23);
16251 LocalContext context;
16252 context->Global()->Set(v8_str("P"), templ->NewInstance());
16253 CompileRun("function C1() {"
16256 "C1.prototype = P;"
16260 "C2.prototype = { };"
16261 "C2.prototype.__proto__ = P;");
16263 v8::Local<v8::Script> script;
16264 script = v8_compile("new C1();");
16265 for (int i = 0; i < 10; i++) {
16266 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16267 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16268 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16271 script = v8_compile("new C2();");
16272 for (int i = 0; i < 10; i++) {
16273 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16274 CHECK_EQ(42, c2->Get(v8_str("x"))->Int32Value());
16275 CHECK_EQ(23, c2->Get(v8_str("y"))->Int32Value());
16280 static void NamedPropertyGetterWhichReturns42(
16281 Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) {
16282 info.GetReturnValue().Set(v8_num(42));
16286 static void NamedPropertySetterWhichSetsYOnThisTo23(
16287 Local<Name> name, Local<Value> value,
16288 const v8::PropertyCallbackInfo<v8::Value>& info) {
16289 if (name->Equals(v8_str("x"))) {
16290 Local<Object>::Cast(info.This())->Set(v8_str("y"), v8_num(23));
16295 THREADED_TEST(InterceptorOnConstructorPrototype) {
16296 v8::Isolate* isolate = CcTest::isolate();
16297 v8::HandleScope scope(isolate);
16298 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16299 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
16300 NamedPropertyGetterWhichReturns42,
16301 NamedPropertySetterWhichSetsYOnThisTo23));
16302 LocalContext context;
16303 context->Global()->Set(v8_str("P"), templ->NewInstance());
16304 CompileRun("function C1() {"
16307 "C1.prototype = P;"
16311 "C2.prototype = { };"
16312 "C2.prototype.__proto__ = P;");
16314 v8::Local<v8::Script> script;
16315 script = v8_compile("new C1();");
16316 for (int i = 0; i < 10; i++) {
16317 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16318 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16319 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16322 script = v8_compile("new C2();");
16323 for (int i = 0; i < 10; i++) {
16324 v8::Handle<v8::Object> c2 = v8::Handle<v8::Object>::Cast(script->Run());
16325 CHECK_EQ(23, c2->Get(v8_str("x"))->Int32Value());
16326 CHECK_EQ(42, c2->Get(v8_str("y"))->Int32Value());
16332 const char* source = "function C1() {"
16335 "C1.prototype = P;";
16337 LocalContext context;
16338 v8::Isolate* isolate = context->GetIsolate();
16339 v8::HandleScope scope(isolate);
16340 v8::Local<v8::Script> script;
16342 // Use a simple object as prototype.
16343 v8::Local<v8::Object> prototype = v8::Object::New(isolate);
16344 prototype->Set(v8_str("y"), v8_num(42));
16345 context->Global()->Set(v8_str("P"), prototype);
16347 // This compile will add the code to the compilation cache.
16348 CompileRun(source);
16350 script = v8_compile("new C1();");
16351 // Allow enough iterations for the inobject slack tracking logic
16352 // to finalize instance size and install the fast construct stub.
16353 for (int i = 0; i < 256; i++) {
16354 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16355 CHECK_EQ(23, c1->Get(v8_str("x"))->Int32Value());
16356 CHECK_EQ(42, c1->Get(v8_str("y"))->Int32Value());
16359 // Use an API object with accessors as prototype.
16360 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
16361 templ->SetAccessor(v8_str("x"), GetterWhichReturns42,
16362 SetterWhichSetsYOnThisTo23);
16363 context->Global()->Set(v8_str("P"), templ->NewInstance());
16365 // This compile will get the code from the compilation cache.
16366 CompileRun(source);
16368 script = v8_compile("new C1();");
16369 for (int i = 0; i < 10; i++) {
16370 v8::Handle<v8::Object> c1 = v8::Handle<v8::Object>::Cast(script->Run());
16371 CHECK_EQ(42, c1->Get(v8_str("x"))->Int32Value());
16372 CHECK_EQ(23, c1->Get(v8_str("y"))->Int32Value());
16376 v8::Isolate* gc_callbacks_isolate = NULL;
16377 int prologue_call_count = 0;
16378 int epilogue_call_count = 0;
16379 int prologue_call_count_second = 0;
16380 int epilogue_call_count_second = 0;
16381 int prologue_call_count_alloc = 0;
16382 int epilogue_call_count_alloc = 0;
16384 void PrologueCallback(v8::GCType, v8::GCCallbackFlags flags) {
16385 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16386 ++prologue_call_count;
16390 void PrologueCallback(v8::Isolate* isolate,
16392 v8::GCCallbackFlags flags) {
16393 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16394 CHECK_EQ(gc_callbacks_isolate, isolate);
16395 ++prologue_call_count;
16399 void EpilogueCallback(v8::GCType, v8::GCCallbackFlags flags) {
16400 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16401 ++epilogue_call_count;
16405 void EpilogueCallback(v8::Isolate* isolate,
16407 v8::GCCallbackFlags flags) {
16408 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16409 CHECK_EQ(gc_callbacks_isolate, isolate);
16410 ++epilogue_call_count;
16414 void PrologueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
16415 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16416 ++prologue_call_count_second;
16420 void PrologueCallbackSecond(v8::Isolate* isolate,
16422 v8::GCCallbackFlags flags) {
16423 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16424 CHECK_EQ(gc_callbacks_isolate, isolate);
16425 ++prologue_call_count_second;
16429 void EpilogueCallbackSecond(v8::GCType, v8::GCCallbackFlags flags) {
16430 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16431 ++epilogue_call_count_second;
16435 void EpilogueCallbackSecond(v8::Isolate* isolate,
16437 v8::GCCallbackFlags flags) {
16438 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16439 CHECK_EQ(gc_callbacks_isolate, isolate);
16440 ++epilogue_call_count_second;
16444 void PrologueCallbackAlloc(v8::Isolate* isolate,
16446 v8::GCCallbackFlags flags) {
16447 v8::HandleScope scope(isolate);
16449 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16450 CHECK_EQ(gc_callbacks_isolate, isolate);
16451 ++prologue_call_count_alloc;
16453 // Simulate full heap to see if we will reenter this callback
16454 SimulateFullSpace(CcTest::heap()->new_space());
16456 Local<Object> obj = Object::New(isolate);
16457 CHECK(!obj.IsEmpty());
16459 CcTest::heap()->CollectAllGarbage(
16460 i::Heap::kAbortIncrementalMarkingMask);
16464 void EpilogueCallbackAlloc(v8::Isolate* isolate,
16466 v8::GCCallbackFlags flags) {
16467 v8::HandleScope scope(isolate);
16469 CHECK_EQ(flags, v8::kNoGCCallbackFlags);
16470 CHECK_EQ(gc_callbacks_isolate, isolate);
16471 ++epilogue_call_count_alloc;
16473 // Simulate full heap to see if we will reenter this callback
16474 SimulateFullSpace(CcTest::heap()->new_space());
16476 Local<Object> obj = Object::New(isolate);
16477 CHECK(!obj.IsEmpty());
16479 CcTest::heap()->CollectAllGarbage(
16480 i::Heap::kAbortIncrementalMarkingMask);
16484 TEST(GCCallbacksOld) {
16485 LocalContext context;
16487 v8::V8::AddGCPrologueCallback(PrologueCallback);
16488 v8::V8::AddGCEpilogueCallback(EpilogueCallback);
16489 CHECK_EQ(0, prologue_call_count);
16490 CHECK_EQ(0, epilogue_call_count);
16491 CcTest::heap()->CollectAllGarbage();
16492 CHECK_EQ(1, prologue_call_count);
16493 CHECK_EQ(1, epilogue_call_count);
16494 v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
16495 v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
16496 CcTest::heap()->CollectAllGarbage();
16497 CHECK_EQ(2, prologue_call_count);
16498 CHECK_EQ(2, epilogue_call_count);
16499 CHECK_EQ(1, prologue_call_count_second);
16500 CHECK_EQ(1, epilogue_call_count_second);
16501 v8::V8::RemoveGCPrologueCallback(PrologueCallback);
16502 v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
16503 CcTest::heap()->CollectAllGarbage();
16504 CHECK_EQ(2, prologue_call_count);
16505 CHECK_EQ(2, epilogue_call_count);
16506 CHECK_EQ(2, prologue_call_count_second);
16507 CHECK_EQ(2, epilogue_call_count_second);
16508 v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
16509 v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
16510 CcTest::heap()->CollectAllGarbage();
16511 CHECK_EQ(2, prologue_call_count);
16512 CHECK_EQ(2, epilogue_call_count);
16513 CHECK_EQ(2, prologue_call_count_second);
16514 CHECK_EQ(2, epilogue_call_count_second);
16518 TEST(GCCallbacks) {
16519 LocalContext context;
16520 v8::Isolate* isolate = context->GetIsolate();
16521 gc_callbacks_isolate = isolate;
16522 isolate->AddGCPrologueCallback(PrologueCallback);
16523 isolate->AddGCEpilogueCallback(EpilogueCallback);
16524 CHECK_EQ(0, prologue_call_count);
16525 CHECK_EQ(0, epilogue_call_count);
16526 CcTest::heap()->CollectAllGarbage();
16527 CHECK_EQ(1, prologue_call_count);
16528 CHECK_EQ(1, epilogue_call_count);
16529 isolate->AddGCPrologueCallback(PrologueCallbackSecond);
16530 isolate->AddGCEpilogueCallback(EpilogueCallbackSecond);
16531 CcTest::heap()->CollectAllGarbage();
16532 CHECK_EQ(2, prologue_call_count);
16533 CHECK_EQ(2, epilogue_call_count);
16534 CHECK_EQ(1, prologue_call_count_second);
16535 CHECK_EQ(1, epilogue_call_count_second);
16536 isolate->RemoveGCPrologueCallback(PrologueCallback);
16537 isolate->RemoveGCEpilogueCallback(EpilogueCallback);
16538 CcTest::heap()->CollectAllGarbage();
16539 CHECK_EQ(2, prologue_call_count);
16540 CHECK_EQ(2, epilogue_call_count);
16541 CHECK_EQ(2, prologue_call_count_second);
16542 CHECK_EQ(2, epilogue_call_count_second);
16543 isolate->RemoveGCPrologueCallback(PrologueCallbackSecond);
16544 isolate->RemoveGCEpilogueCallback(EpilogueCallbackSecond);
16545 CcTest::heap()->CollectAllGarbage();
16546 CHECK_EQ(2, prologue_call_count);
16547 CHECK_EQ(2, epilogue_call_count);
16548 CHECK_EQ(2, prologue_call_count_second);
16549 CHECK_EQ(2, epilogue_call_count_second);
16551 CHECK_EQ(0, prologue_call_count_alloc);
16552 CHECK_EQ(0, epilogue_call_count_alloc);
16553 isolate->AddGCPrologueCallback(PrologueCallbackAlloc);
16554 isolate->AddGCEpilogueCallback(EpilogueCallbackAlloc);
16555 CcTest::heap()->CollectAllGarbage(
16556 i::Heap::kAbortIncrementalMarkingMask);
16557 CHECK_EQ(1, prologue_call_count_alloc);
16558 CHECK_EQ(1, epilogue_call_count_alloc);
16559 isolate->RemoveGCPrologueCallback(PrologueCallbackAlloc);
16560 isolate->RemoveGCEpilogueCallback(EpilogueCallbackAlloc);
16564 THREADED_TEST(TwoByteStringInOneByteCons) {
16565 // See Chromium issue 47824.
16566 LocalContext context;
16567 v8::HandleScope scope(context->GetIsolate());
16569 const char* init_code =
16570 "var str1 = 'abelspendabel';"
16571 "var str2 = str1 + str1 + str1;"
16573 Local<Value> result = CompileRun(init_code);
16575 Local<Value> indexof = CompileRun("str2.indexOf('els')");
16576 Local<Value> lastindexof = CompileRun("str2.lastIndexOf('dab')");
16578 CHECK(result->IsString());
16579 i::Handle<i::String> string = v8::Utils::OpenHandle(String::Cast(*result));
16580 int length = string->length();
16581 CHECK(string->IsOneByteRepresentation());
16583 i::Handle<i::String> flat_string = i::String::Flatten(string);
16585 CHECK(string->IsOneByteRepresentation());
16586 CHECK(flat_string->IsOneByteRepresentation());
16588 // Create external resource.
16589 uint16_t* uc16_buffer = new uint16_t[length + 1];
16591 i::String::WriteToFlat(*flat_string, uc16_buffer, 0, length);
16592 uc16_buffer[length] = 0;
16594 TestResource resource(uc16_buffer);
16596 flat_string->MakeExternal(&resource);
16598 CHECK(flat_string->IsTwoByteRepresentation());
16600 // If the cons string has been short-circuited, skip the following checks.
16601 if (!string.is_identical_to(flat_string)) {
16602 // At this point, we should have a Cons string which is flat and one-byte,
16603 // with a first half that is a two-byte string (although it only contains
16604 // one-byte characters). This is a valid sequence of steps, and it can
16605 // happen in real pages.
16606 CHECK(string->IsOneByteRepresentation());
16607 i::ConsString* cons = i::ConsString::cast(*string);
16608 CHECK_EQ(0, cons->second()->length());
16609 CHECK(cons->first()->IsTwoByteRepresentation());
16612 // Check that some string operations work.
16615 Local<Value> reresult = CompileRun("str2.match(/abel/g).length;");
16616 CHECK_EQ(6, reresult->Int32Value());
16619 reresult = CompileRun("str2.match(/abe./g).length;");
16620 CHECK_EQ(6, reresult->Int32Value());
16622 reresult = CompileRun("str2.search(/bel/g);");
16623 CHECK_EQ(1, reresult->Int32Value());
16625 reresult = CompileRun("str2.search(/be./g);");
16626 CHECK_EQ(1, reresult->Int32Value());
16628 ExpectTrue("/bel/g.test(str2);");
16630 ExpectTrue("/be./g.test(str2);");
16632 reresult = CompileRun("/bel/g.exec(str2);");
16633 CHECK(!reresult->IsNull());
16635 reresult = CompileRun("/be./g.exec(str2);");
16636 CHECK(!reresult->IsNull());
16638 ExpectString("str2.substring(2, 10);", "elspenda");
16640 ExpectString("str2.substring(2, 20);", "elspendabelabelspe");
16642 ExpectString("str2.charAt(2);", "e");
16644 ExpectObject("str2.indexOf('els');", indexof);
16646 ExpectObject("str2.lastIndexOf('dab');", lastindexof);
16648 reresult = CompileRun("str2.charCodeAt(2);");
16649 CHECK_EQ(static_cast<int32_t>('e'), reresult->Int32Value());
16653 TEST(ContainsOnlyOneByte) {
16654 v8::V8::Initialize();
16655 v8::Isolate* isolate = CcTest::isolate();
16656 v8::HandleScope scope(isolate);
16657 // Make a buffer long enough that it won't automatically be converted.
16658 const int length = 512;
16659 // Ensure word aligned assignment.
16660 const int aligned_length = length*sizeof(uintptr_t)/sizeof(uint16_t);
16661 v8::base::SmartArrayPointer<uintptr_t> aligned_contents(
16662 new uintptr_t[aligned_length]);
16663 uint16_t* string_contents =
16664 reinterpret_cast<uint16_t*>(aligned_contents.get());
16665 // Set to contain only one byte.
16666 for (int i = 0; i < length-1; i++) {
16667 string_contents[i] = 0x41;
16669 string_contents[length-1] = 0;
16671 Handle<String> string =
16672 String::NewExternal(isolate,
16673 new TestResource(string_contents, NULL, false));
16674 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16675 // Counter example.
16676 string = String::NewFromTwoByte(isolate, string_contents);
16677 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
16678 // Test left right and balanced cons strings.
16679 Handle<String> base = String::NewFromUtf8(isolate, "a");
16680 Handle<String> left = base;
16681 Handle<String> right = base;
16682 for (int i = 0; i < 1000; i++) {
16683 left = String::Concat(base, left);
16684 right = String::Concat(right, base);
16686 Handle<String> balanced = String::Concat(left, base);
16687 balanced = String::Concat(balanced, right);
16688 Handle<String> cons_strings[] = {left, balanced, right};
16689 Handle<String> two_byte =
16690 String::NewExternal(isolate,
16691 new TestResource(string_contents, NULL, false));
16692 USE(two_byte); USE(cons_strings);
16693 for (size_t i = 0; i < arraysize(cons_strings); i++) {
16694 // Base assumptions.
16695 string = cons_strings[i];
16696 CHECK(string->IsOneByte() && string->ContainsOnlyOneByte());
16697 // Test left and right concatentation.
16698 string = String::Concat(two_byte, cons_strings[i]);
16699 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16700 string = String::Concat(cons_strings[i], two_byte);
16701 CHECK(!string->IsOneByte() && string->ContainsOnlyOneByte());
16703 // Set bits in different positions
16704 // for strings of different lengths and alignments.
16705 for (int alignment = 0; alignment < 7; alignment++) {
16706 for (int size = 2; alignment + size < length; size *= 2) {
16707 int zero_offset = size + alignment;
16708 string_contents[zero_offset] = 0;
16709 for (int i = 0; i < size; i++) {
16710 int shift = 8 + (i % 7);
16711 string_contents[alignment + i] = 1 << shift;
16712 string = String::NewExternal(
16714 new TestResource(string_contents + alignment, NULL, false));
16715 CHECK_EQ(size, string->Length());
16716 CHECK(!string->ContainsOnlyOneByte());
16717 string_contents[alignment + i] = 0x41;
16719 string_contents[zero_offset] = 0x41;
16725 // Failed access check callback that performs a GC on each invocation.
16726 void FailedAccessCheckCallbackGC(Local<v8::Object> target,
16727 v8::AccessType type,
16728 Local<v8::Value> data) {
16729 CcTest::heap()->CollectAllGarbage();
16730 CcTest::isolate()->ThrowException(
16731 v8::Exception::Error(v8_str("cross context")));
16735 TEST(GCInFailedAccessCheckCallback) {
16736 // Install a failed access check callback that performs a GC on each
16737 // invocation. Then force the callback to be called from va
16739 v8::V8::Initialize();
16740 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckCallbackGC);
16742 v8::Isolate* isolate = CcTest::isolate();
16743 v8::HandleScope scope(isolate);
16745 // Create an ObjectTemplate for global objects and install access
16746 // check callbacks that will block access.
16747 v8::Handle<v8::ObjectTemplate> global_template =
16748 v8::ObjectTemplate::New(isolate);
16749 global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL,
16750 v8::Handle<v8::Value>());
16752 // Create a context and set an x property on it's global object.
16753 LocalContext context0(NULL, global_template);
16754 context0->Global()->Set(v8_str("x"), v8_num(42));
16755 v8::Handle<v8::Object> global0 = context0->Global();
16757 // Create a context with a different security token so that the
16758 // failed access check callback will be called on each access.
16759 LocalContext context1(NULL, global_template);
16760 context1->Global()->Set(v8_str("other"), global0);
16762 v8::TryCatch try_catch(isolate);
16764 // Get property with failed access check.
16765 CHECK(CompileRun("other.x").IsEmpty());
16766 CHECK(try_catch.HasCaught());
16769 // Get element with failed access check.
16770 CHECK(CompileRun("other[0]").IsEmpty());
16771 CHECK(try_catch.HasCaught());
16774 // Set property with failed access check.
16775 CHECK(CompileRun("other.x = new Object()").IsEmpty());
16776 CHECK(try_catch.HasCaught());
16779 // Set element with failed access check.
16780 CHECK(CompileRun("other[0] = new Object()").IsEmpty());
16781 CHECK(try_catch.HasCaught());
16784 // Get property attribute with failed access check.
16785 CHECK(CompileRun("\'x\' in other").IsEmpty());
16786 CHECK(try_catch.HasCaught());
16789 // Get property attribute for element with failed access check.
16790 CHECK(CompileRun("0 in other").IsEmpty());
16791 CHECK(try_catch.HasCaught());
16794 // Delete property.
16795 CHECK(CompileRun("delete other.x").IsEmpty());
16796 CHECK(try_catch.HasCaught());
16800 CHECK_EQ(false, global0->Delete(0));
16804 global0->SetAccessor(v8_str("x"), GetXValue, NULL, v8_str("x")));
16806 // Define JavaScript accessor.
16808 "Object.prototype.__defineGetter__.call("
16809 " other, \'x\', function() { return 42; })").IsEmpty());
16810 CHECK(try_catch.HasCaught());
16815 "Object.prototype.__lookupGetter__.call("
16816 " other, \'x\')").IsEmpty());
16817 CHECK(try_catch.HasCaught());
16822 "Object.prototype.hasOwnProperty.call("
16823 "other, \'0\')").IsEmpty());
16824 CHECK(try_catch.HasCaught());
16827 CHECK_EQ(false, global0->HasRealIndexedProperty(0));
16828 CHECK_EQ(false, global0->HasRealNamedProperty(v8_str("x")));
16829 CHECK_EQ(false, global0->HasRealNamedCallbackProperty(v8_str("x")));
16831 // Reset the failed access check callback so it does not influence
16832 // the other tests.
16833 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
16837 TEST(IsolateNewDispose) {
16838 v8::Isolate* current_isolate = CcTest::isolate();
16839 v8::Isolate::CreateParams create_params;
16840 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16841 v8::Isolate* isolate = v8::Isolate::New(create_params);
16842 CHECK(isolate != NULL);
16843 CHECK(current_isolate != isolate);
16844 CHECK(current_isolate == CcTest::isolate());
16846 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16847 last_location = last_message = NULL;
16848 isolate->Dispose();
16849 CHECK(!last_location);
16850 CHECK(!last_message);
16854 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) {
16855 v8::Isolate::CreateParams create_params;
16856 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16857 v8::Isolate* isolate = v8::Isolate::New(create_params);
16859 v8::Isolate::Scope i_scope(isolate);
16860 v8::HandleScope scope(isolate);
16861 LocalContext context(isolate);
16862 // Run something in this isolate.
16863 ExpectTrue("true");
16864 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
16865 last_location = last_message = NULL;
16866 // Still entered, should fail.
16867 isolate->Dispose();
16868 CHECK(last_location);
16869 CHECK(last_message);
16871 isolate->Dispose();
16875 static void BreakArrayGuarantees(const char* script) {
16876 v8::Isolate::CreateParams create_params;
16877 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16878 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
16880 v8::Persistent<v8::Context> context1;
16882 v8::HandleScope scope(isolate1);
16883 context1.Reset(isolate1, Context::New(isolate1));
16887 v8::HandleScope scope(isolate1);
16888 v8::Local<v8::Context> context =
16889 v8::Local<v8::Context>::New(isolate1, context1);
16890 v8::Context::Scope context_scope(context);
16891 v8::internal::Isolate* i_isolate =
16892 reinterpret_cast<v8::internal::Isolate*>(isolate1);
16893 CHECK_EQ(true, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
16894 // Run something in new isolate.
16895 CompileRun(script);
16896 CHECK_EQ(false, i_isolate->IsFastArrayConstructorPrototypeChainIntact());
16899 isolate1->Dispose();
16903 TEST(VerifyArrayPrototypeGuarantees) {
16904 // Break fast array hole handling by element changes.
16905 BreakArrayGuarantees("[].__proto__[1] = 3;");
16906 BreakArrayGuarantees("Object.prototype[3] = 'three';");
16907 BreakArrayGuarantees("Array.prototype.push(1);");
16908 BreakArrayGuarantees("Array.prototype.unshift(1);");
16909 // Break fast array hole handling by changing length.
16910 BreakArrayGuarantees("Array.prototype.length = 30;");
16911 // Break fast array hole handling by prototype structure changes.
16912 BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
16913 // By sending elements to dictionary mode.
16914 BreakArrayGuarantees(
16915 "Object.defineProperty(Array.prototype, 0, {"
16916 " get: function() { return 3; }});");
16917 BreakArrayGuarantees(
16918 "Object.defineProperty(Object.prototype, 0, {"
16919 " get: function() { return 3; }});");
16923 TEST(RunTwoIsolatesOnSingleThread) {
16925 v8::Isolate::CreateParams create_params;
16926 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
16927 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
16929 v8::Persistent<v8::Context> context1;
16931 v8::HandleScope scope(isolate1);
16932 context1.Reset(isolate1, Context::New(isolate1));
16936 v8::HandleScope scope(isolate1);
16937 v8::Local<v8::Context> context =
16938 v8::Local<v8::Context>::New(isolate1, context1);
16939 v8::Context::Scope context_scope(context);
16940 // Run something in new isolate.
16941 CompileRun("var foo = 'isolate 1';");
16942 ExpectString("function f() { return foo; }; f()", "isolate 1");
16946 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
16947 v8::Persistent<v8::Context> context2;
16950 v8::Isolate::Scope iscope(isolate2);
16951 v8::HandleScope scope(isolate2);
16952 context2.Reset(isolate2, Context::New(isolate2));
16953 v8::Local<v8::Context> context =
16954 v8::Local<v8::Context>::New(isolate2, context2);
16955 v8::Context::Scope context_scope(context);
16957 // Run something in new isolate.
16958 CompileRun("var foo = 'isolate 2';");
16959 ExpectString("function f() { return foo; }; f()", "isolate 2");
16963 v8::HandleScope scope(isolate1);
16964 v8::Local<v8::Context> context =
16965 v8::Local<v8::Context>::New(isolate1, context1);
16966 v8::Context::Scope context_scope(context);
16967 // Now again in isolate 1
16968 ExpectString("function f() { return foo; }; f()", "isolate 1");
16973 // Run some stuff in default isolate.
16974 v8::Persistent<v8::Context> context_default;
16976 v8::Isolate* isolate = CcTest::isolate();
16977 v8::Isolate::Scope iscope(isolate);
16978 v8::HandleScope scope(isolate);
16979 context_default.Reset(isolate, Context::New(isolate));
16983 v8::HandleScope scope(CcTest::isolate());
16984 v8::Local<v8::Context> context =
16985 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
16986 v8::Context::Scope context_scope(context);
16987 // Variables in other isolates should be not available, verify there
16988 // is an exception.
16989 ExpectTrue("function f() {"
16997 "var isDefaultIsolate = true;"
17004 v8::Isolate::Scope iscope(isolate2);
17005 v8::HandleScope scope(isolate2);
17006 v8::Local<v8::Context> context =
17007 v8::Local<v8::Context>::New(isolate2, context2);
17008 v8::Context::Scope context_scope(context);
17009 ExpectString("function f() { return foo; }; f()", "isolate 2");
17013 v8::HandleScope scope(v8::Isolate::GetCurrent());
17014 v8::Local<v8::Context> context =
17015 v8::Local<v8::Context>::New(v8::Isolate::GetCurrent(), context1);
17016 v8::Context::Scope context_scope(context);
17017 ExpectString("function f() { return foo; }; f()", "isolate 1");
17021 v8::Isolate::Scope iscope(isolate2);
17028 v8::V8::SetFatalErrorHandler(StoringErrorCallback);
17029 last_location = last_message = NULL;
17031 isolate1->Dispose();
17032 CHECK(!last_location);
17033 CHECK(!last_message);
17035 isolate2->Dispose();
17036 CHECK(!last_location);
17037 CHECK(!last_message);
17039 // Check that default isolate still runs.
17041 v8::HandleScope scope(CcTest::isolate());
17042 v8::Local<v8::Context> context =
17043 v8::Local<v8::Context>::New(CcTest::isolate(), context_default);
17044 v8::Context::Scope context_scope(context);
17045 ExpectTrue("function f() { return isDefaultIsolate; }; f()");
17050 static int CalcFibonacci(v8::Isolate* isolate, int limit) {
17051 v8::Isolate::Scope isolate_scope(isolate);
17052 v8::HandleScope scope(isolate);
17053 LocalContext context(isolate);
17054 i::ScopedVector<char> code(1024);
17055 i::SNPrintF(code, "function fib(n) {"
17056 " if (n <= 2) return 1;"
17057 " return fib(n-1) + fib(n-2);"
17060 Local<Value> value = CompileRun(code.start());
17061 CHECK(value->IsNumber());
17062 return static_cast<int>(value->NumberValue());
17065 class IsolateThread : public v8::base::Thread {
17067 explicit IsolateThread(int fib_limit)
17068 : Thread(Options("IsolateThread")), fib_limit_(fib_limit), result_(0) {}
17071 v8::Isolate::CreateParams create_params;
17072 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17073 v8::Isolate* isolate = v8::Isolate::New(create_params);
17074 result_ = CalcFibonacci(isolate, fib_limit_);
17075 isolate->Dispose();
17078 int result() { return result_; }
17086 TEST(MultipleIsolatesOnIndividualThreads) {
17087 IsolateThread thread1(21);
17088 IsolateThread thread2(12);
17090 // Compute some fibonacci numbers on 3 threads in 3 isolates.
17094 int result1 = CalcFibonacci(CcTest::isolate(), 21);
17095 int result2 = CalcFibonacci(CcTest::isolate(), 12);
17100 // Compare results. The actual fibonacci numbers for 12 and 21 are taken
17101 // (I'm lazy!) from http://en.wikipedia.org/wiki/Fibonacci_number
17102 CHECK_EQ(result1, 10946);
17103 CHECK_EQ(result2, 144);
17104 CHECK_EQ(result1, thread1.result());
17105 CHECK_EQ(result2, thread2.result());
17109 TEST(IsolateDifferentContexts) {
17110 v8::Isolate::CreateParams create_params;
17111 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17112 v8::Isolate* isolate = v8::Isolate::New(create_params);
17113 Local<v8::Context> context;
17115 v8::Isolate::Scope isolate_scope(isolate);
17116 v8::HandleScope handle_scope(isolate);
17117 context = v8::Context::New(isolate);
17118 v8::Context::Scope context_scope(context);
17119 Local<Value> v = CompileRun("2");
17120 CHECK(v->IsNumber());
17121 CHECK_EQ(2, static_cast<int>(v->NumberValue()));
17124 v8::Isolate::Scope isolate_scope(isolate);
17125 v8::HandleScope handle_scope(isolate);
17126 context = v8::Context::New(isolate);
17127 v8::Context::Scope context_scope(context);
17128 Local<Value> v = CompileRun("22");
17129 CHECK(v->IsNumber());
17130 CHECK_EQ(22, static_cast<int>(v->NumberValue()));
17132 isolate->Dispose();
17135 class InitDefaultIsolateThread : public v8::base::Thread {
17138 SetResourceConstraints,
17140 SetCounterFunction,
17141 SetCreateHistogramFunction,
17142 SetAddHistogramSampleFunction
17145 explicit InitDefaultIsolateThread(TestCase testCase)
17146 : Thread(Options("InitDefaultIsolateThread")),
17147 testCase_(testCase),
17151 v8::Isolate::CreateParams create_params;
17152 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
17153 const intptr_t pageSizeMult =
17154 v8::internal::Page::kPageSize / v8::internal::MB;
17155 switch (testCase_) {
17156 case SetResourceConstraints: {
17157 create_params.constraints.set_max_semi_space_size(1 * pageSizeMult);
17158 create_params.constraints.set_max_old_space_size(4 * pageSizeMult);
17164 v8::Isolate* isolate = v8::Isolate::New(create_params);
17166 switch (testCase_) {
17167 case SetResourceConstraints:
17168 // Already handled in pre-Isolate-creation block.
17171 case SetFatalHandler:
17172 v8::V8::SetFatalErrorHandler(NULL);
17175 case SetCounterFunction:
17176 CcTest::isolate()->SetCounterFunction(NULL);
17179 case SetCreateHistogramFunction:
17180 CcTest::isolate()->SetCreateHistogramFunction(NULL);
17183 case SetAddHistogramSampleFunction:
17184 CcTest::isolate()->SetAddHistogramSampleFunction(NULL);
17188 isolate->Dispose();
17192 bool result() { return result_; }
17195 TestCase testCase_;
17200 static void InitializeTestHelper(InitDefaultIsolateThread::TestCase testCase) {
17201 InitDefaultIsolateThread thread(testCase);
17204 CHECK_EQ(thread.result(), true);
17208 TEST(InitializeDefaultIsolateOnSecondaryThread1) {
17209 InitializeTestHelper(InitDefaultIsolateThread::SetResourceConstraints);
17213 TEST(InitializeDefaultIsolateOnSecondaryThread2) {
17214 InitializeTestHelper(InitDefaultIsolateThread::SetFatalHandler);
17218 TEST(InitializeDefaultIsolateOnSecondaryThread3) {
17219 InitializeTestHelper(InitDefaultIsolateThread::SetCounterFunction);
17223 TEST(InitializeDefaultIsolateOnSecondaryThread4) {
17224 InitializeTestHelper(InitDefaultIsolateThread::SetCreateHistogramFunction);
17228 TEST(InitializeDefaultIsolateOnSecondaryThread5) {
17229 InitializeTestHelper(InitDefaultIsolateThread::SetAddHistogramSampleFunction);
17233 TEST(StringCheckMultipleContexts) {
17235 "(function() { return \"a\".charAt(0); })()";
17238 // Run the code twice in the first context to initialize the call IC.
17239 LocalContext context1;
17240 v8::HandleScope scope(context1->GetIsolate());
17241 ExpectString(code, "a");
17242 ExpectString(code, "a");
17246 // Change the String.prototype in the second context and check
17247 // that the right function gets called.
17248 LocalContext context2;
17249 v8::HandleScope scope(context2->GetIsolate());
17250 CompileRun("String.prototype.charAt = function() { return \"not a\"; }");
17251 ExpectString(code, "not a");
17256 TEST(NumberCheckMultipleContexts) {
17258 "(function() { return (42).toString(); })()";
17261 // Run the code twice in the first context to initialize the call IC.
17262 LocalContext context1;
17263 v8::HandleScope scope(context1->GetIsolate());
17264 ExpectString(code, "42");
17265 ExpectString(code, "42");
17269 // Change the Number.prototype in the second context and check
17270 // that the right function gets called.
17271 LocalContext context2;
17272 v8::HandleScope scope(context2->GetIsolate());
17273 CompileRun("Number.prototype.toString = function() { return \"not 42\"; }");
17274 ExpectString(code, "not 42");
17279 TEST(BooleanCheckMultipleContexts) {
17281 "(function() { return true.toString(); })()";
17284 // Run the code twice in the first context to initialize the call IC.
17285 LocalContext context1;
17286 v8::HandleScope scope(context1->GetIsolate());
17287 ExpectString(code, "true");
17288 ExpectString(code, "true");
17292 // Change the Boolean.prototype in the second context and check
17293 // that the right function gets called.
17294 LocalContext context2;
17295 v8::HandleScope scope(context2->GetIsolate());
17296 CompileRun("Boolean.prototype.toString = function() { return \"\"; }");
17297 ExpectString(code, "");
17302 TEST(DontDeleteCellLoadIC) {
17303 const char* function_code =
17304 "function readCell() { while (true) { return cell; } }";
17307 // Run the code twice in the first context to initialize the load
17308 // IC for a don't delete cell.
17309 LocalContext context1;
17310 v8::HandleScope scope(context1->GetIsolate());
17311 CompileRun("var cell = \"first\";");
17312 ExpectBoolean("delete cell", false);
17313 CompileRun(function_code);
17314 ExpectString("readCell()", "first");
17315 ExpectString("readCell()", "first");
17319 // Use a deletable cell in the second context.
17320 LocalContext context2;
17321 v8::HandleScope scope(context2->GetIsolate());
17322 CompileRun("cell = \"second\";");
17323 CompileRun(function_code);
17324 ExpectString("readCell()", "second");
17325 ExpectBoolean("delete cell", true);
17326 ExpectString("(function() {"
17328 " return readCell();"
17330 " return e.toString();"
17333 "ReferenceError: cell is not defined");
17334 CompileRun("cell = \"new_second\";");
17335 CcTest::heap()->CollectAllGarbage();
17336 ExpectString("readCell()", "new_second");
17337 ExpectString("readCell()", "new_second");
17342 class Visitor42 : public v8::PersistentHandleVisitor {
17344 explicit Visitor42(v8::Persistent<v8::Object>* object)
17345 : counter_(0), object_(object) { }
17347 virtual void VisitPersistentHandle(Persistent<Value>* value,
17348 uint16_t class_id) {
17349 if (class_id != 42) return;
17350 CHECK_EQ(42, value->WrapperClassId());
17351 v8::Isolate* isolate = CcTest::isolate();
17352 v8::HandleScope handle_scope(isolate);
17353 v8::Handle<v8::Value> handle = v8::Local<v8::Value>::New(isolate, *value);
17354 v8::Handle<v8::Value> object =
17355 v8::Local<v8::Object>::New(isolate, *object_);
17356 CHECK(handle->IsObject());
17357 CHECK(Handle<Object>::Cast(handle)->Equals(object));
17362 v8::Persistent<v8::Object>* object_;
17366 TEST(PersistentHandleVisitor) {
17367 LocalContext context;
17368 v8::Isolate* isolate = context->GetIsolate();
17369 v8::HandleScope scope(isolate);
17370 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
17371 CHECK_EQ(0, object.WrapperClassId());
17372 object.SetWrapperClassId(42);
17373 CHECK_EQ(42, object.WrapperClassId());
17375 Visitor42 visitor(&object);
17376 v8::V8::VisitHandlesWithClassIds(isolate, &visitor);
17377 CHECK_EQ(1, visitor.counter_);
17383 TEST(WrapperClassId) {
17384 LocalContext context;
17385 v8::Isolate* isolate = context->GetIsolate();
17386 v8::HandleScope scope(isolate);
17387 v8::Persistent<v8::Object> object(isolate, v8::Object::New(isolate));
17388 CHECK_EQ(0, object.WrapperClassId());
17389 object.SetWrapperClassId(65535);
17390 CHECK_EQ(65535, object.WrapperClassId());
17395 TEST(PersistentHandleInNewSpaceVisitor) {
17396 LocalContext context;
17397 v8::Isolate* isolate = context->GetIsolate();
17398 v8::HandleScope scope(isolate);
17399 v8::Persistent<v8::Object> object1(isolate, v8::Object::New(isolate));
17400 CHECK_EQ(0, object1.WrapperClassId());
17401 object1.SetWrapperClassId(42);
17402 CHECK_EQ(42, object1.WrapperClassId());
17404 CcTest::heap()->CollectAllGarbage();
17405 CcTest::heap()->CollectAllGarbage();
17407 v8::Persistent<v8::Object> object2(isolate, v8::Object::New(isolate));
17408 CHECK_EQ(0, object2.WrapperClassId());
17409 object2.SetWrapperClassId(42);
17410 CHECK_EQ(42, object2.WrapperClassId());
17412 Visitor42 visitor(&object2);
17413 v8::V8::VisitHandlesForPartialDependence(isolate, &visitor);
17414 CHECK_EQ(1, visitor.counter_);
17422 LocalContext context;
17423 v8::HandleScope scope(context->GetIsolate());
17425 v8::Handle<v8::RegExp> re = v8::RegExp::New(v8_str("foo"), v8::RegExp::kNone);
17426 CHECK(re->IsRegExp());
17427 CHECK(re->GetSource()->Equals(v8_str("foo")));
17428 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17430 re = v8::RegExp::New(v8_str("bar"),
17431 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17432 v8::RegExp::kGlobal));
17433 CHECK(re->IsRegExp());
17434 CHECK(re->GetSource()->Equals(v8_str("bar")));
17435 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kGlobal,
17436 static_cast<int>(re->GetFlags()));
17438 re = v8::RegExp::New(v8_str("baz"),
17439 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17440 v8::RegExp::kMultiline));
17441 CHECK(re->IsRegExp());
17442 CHECK(re->GetSource()->Equals(v8_str("baz")));
17443 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
17444 static_cast<int>(re->GetFlags()));
17446 re = CompileRun("/quux/").As<v8::RegExp>();
17447 CHECK(re->IsRegExp());
17448 CHECK(re->GetSource()->Equals(v8_str("quux")));
17449 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17451 re = CompileRun("/quux/gm").As<v8::RegExp>();
17452 CHECK(re->IsRegExp());
17453 CHECK(re->GetSource()->Equals(v8_str("quux")));
17454 CHECK_EQ(v8::RegExp::kGlobal | v8::RegExp::kMultiline,
17455 static_cast<int>(re->GetFlags()));
17457 // Override the RegExp constructor and check the API constructor
17459 CompileRun("RegExp = function() {}");
17461 re = v8::RegExp::New(v8_str("foobar"), v8::RegExp::kNone);
17462 CHECK(re->IsRegExp());
17463 CHECK(re->GetSource()->Equals(v8_str("foobar")));
17464 CHECK_EQ(v8::RegExp::kNone, re->GetFlags());
17466 re = v8::RegExp::New(v8_str("foobarbaz"),
17467 static_cast<v8::RegExp::Flags>(v8::RegExp::kIgnoreCase |
17468 v8::RegExp::kMultiline));
17469 CHECK(re->IsRegExp());
17470 CHECK(re->GetSource()->Equals(v8_str("foobarbaz")));
17471 CHECK_EQ(v8::RegExp::kIgnoreCase | v8::RegExp::kMultiline,
17472 static_cast<int>(re->GetFlags()));
17474 context->Global()->Set(v8_str("re"), re);
17475 ExpectTrue("re.test('FoobarbaZ')");
17477 // RegExps are objects on which you can set properties.
17478 re->Set(v8_str("property"), v8::Integer::New(context->GetIsolate(), 32));
17479 v8::Handle<v8::Value> value(CompileRun("re.property"));
17480 CHECK_EQ(32, value->Int32Value());
17482 v8::TryCatch try_catch(context->GetIsolate());
17483 re = v8::RegExp::New(v8_str("foo["), v8::RegExp::kNone);
17484 CHECK(re.IsEmpty());
17485 CHECK(try_catch.HasCaught());
17486 context->Global()->Set(v8_str("ex"), try_catch.Exception());
17487 ExpectTrue("ex instanceof SyntaxError");
17491 THREADED_TEST(Equals) {
17492 LocalContext localContext;
17493 v8::HandleScope handleScope(localContext->GetIsolate());
17495 v8::Handle<v8::Object> globalProxy = localContext->Global();
17496 v8::Handle<Value> global = globalProxy->GetPrototype();
17498 CHECK(global->StrictEquals(global));
17499 CHECK(!global->StrictEquals(globalProxy));
17500 CHECK(!globalProxy->StrictEquals(global));
17501 CHECK(globalProxy->StrictEquals(globalProxy));
17503 CHECK(global->Equals(global));
17504 CHECK(!global->Equals(globalProxy));
17505 CHECK(!globalProxy->Equals(global));
17506 CHECK(globalProxy->Equals(globalProxy));
17510 static void Getter(v8::Local<v8::Name> property,
17511 const v8::PropertyCallbackInfo<v8::Value>& info) {
17512 info.GetReturnValue().Set(v8_str("42!"));
17516 static void Enumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
17517 v8::Handle<v8::Array> result = v8::Array::New(info.GetIsolate());
17518 result->Set(0, v8_str("universalAnswer"));
17519 info.GetReturnValue().Set(result);
17523 TEST(NamedEnumeratorAndForIn) {
17524 LocalContext context;
17525 v8::Isolate* isolate = context->GetIsolate();
17526 v8::HandleScope handle_scope(isolate);
17527 v8::Context::Scope context_scope(context.local());
17529 v8::Handle<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
17530 tmpl->SetHandler(v8::NamedPropertyHandlerConfiguration(Getter, NULL, NULL,
17531 NULL, Enumerator));
17532 context->Global()->Set(v8_str("o"), tmpl->NewInstance());
17533 v8::Handle<v8::Array> result = v8::Handle<v8::Array>::Cast(CompileRun(
17534 "var result = []; for (var k in o) result.push(k); result"));
17535 CHECK_EQ(1u, result->Length());
17536 CHECK(v8_str("universalAnswer")->Equals(result->Get(0)));
17540 TEST(DefinePropertyPostDetach) {
17541 LocalContext context;
17542 v8::HandleScope scope(context->GetIsolate());
17543 v8::Handle<v8::Object> proxy = context->Global();
17544 v8::Handle<v8::Function> define_property =
17545 CompileRun("(function() {"
17546 " Object.defineProperty("
17549 " { configurable: true, enumerable: true, value: 3 });"
17550 "})").As<Function>();
17551 context->DetachGlobal();
17552 define_property->Call(proxy, 0, NULL);
17556 static void InstallContextId(v8::Handle<Context> context, int id) {
17557 Context::Scope scope(context);
17558 CompileRun("Object.prototype").As<Object>()->
17559 Set(v8_str("context_id"), v8::Integer::New(context->GetIsolate(), id));
17563 static void CheckContextId(v8::Handle<Object> object, int expected) {
17564 CHECK_EQ(expected, object->Get(v8_str("context_id"))->Int32Value());
17568 THREADED_TEST(CreationContext) {
17569 v8::Isolate* isolate = CcTest::isolate();
17570 HandleScope handle_scope(isolate);
17571 Handle<Context> context1 = Context::New(isolate);
17572 InstallContextId(context1, 1);
17573 Handle<Context> context2 = Context::New(isolate);
17574 InstallContextId(context2, 2);
17575 Handle<Context> context3 = Context::New(isolate);
17576 InstallContextId(context3, 3);
17578 Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
17580 Local<Object> object1;
17581 Local<Function> func1;
17583 Context::Scope scope(context1);
17584 object1 = Object::New(isolate);
17585 func1 = tmpl->GetFunction();
17588 Local<Object> object2;
17589 Local<Function> func2;
17591 Context::Scope scope(context2);
17592 object2 = Object::New(isolate);
17593 func2 = tmpl->GetFunction();
17596 Local<Object> instance1;
17597 Local<Object> instance2;
17600 Context::Scope scope(context3);
17601 instance1 = func1->NewInstance();
17602 instance2 = func2->NewInstance();
17606 Handle<Context> other_context = Context::New(isolate);
17607 Context::Scope scope(other_context);
17608 CHECK(object1->CreationContext() == context1);
17609 CheckContextId(object1, 1);
17610 CHECK(func1->CreationContext() == context1);
17611 CheckContextId(func1, 1);
17612 CHECK(instance1->CreationContext() == context1);
17613 CheckContextId(instance1, 1);
17614 CHECK(object2->CreationContext() == context2);
17615 CheckContextId(object2, 2);
17616 CHECK(func2->CreationContext() == context2);
17617 CheckContextId(func2, 2);
17618 CHECK(instance2->CreationContext() == context2);
17619 CheckContextId(instance2, 2);
17623 Context::Scope scope(context1);
17624 CHECK(object1->CreationContext() == context1);
17625 CheckContextId(object1, 1);
17626 CHECK(func1->CreationContext() == context1);
17627 CheckContextId(func1, 1);
17628 CHECK(instance1->CreationContext() == context1);
17629 CheckContextId(instance1, 1);
17630 CHECK(object2->CreationContext() == context2);
17631 CheckContextId(object2, 2);
17632 CHECK(func2->CreationContext() == context2);
17633 CheckContextId(func2, 2);
17634 CHECK(instance2->CreationContext() == context2);
17635 CheckContextId(instance2, 2);
17639 Context::Scope scope(context2);
17640 CHECK(object1->CreationContext() == context1);
17641 CheckContextId(object1, 1);
17642 CHECK(func1->CreationContext() == context1);
17643 CheckContextId(func1, 1);
17644 CHECK(instance1->CreationContext() == context1);
17645 CheckContextId(instance1, 1);
17646 CHECK(object2->CreationContext() == context2);
17647 CheckContextId(object2, 2);
17648 CHECK(func2->CreationContext() == context2);
17649 CheckContextId(func2, 2);
17650 CHECK(instance2->CreationContext() == context2);
17651 CheckContextId(instance2, 2);
17656 THREADED_TEST(CreationContextOfJsFunction) {
17657 HandleScope handle_scope(CcTest::isolate());
17658 Handle<Context> context = Context::New(CcTest::isolate());
17659 InstallContextId(context, 1);
17661 Local<Object> function;
17663 Context::Scope scope(context);
17664 function = CompileRun("function foo() {}; foo").As<Object>();
17667 Handle<Context> other_context = Context::New(CcTest::isolate());
17668 Context::Scope scope(other_context);
17669 CHECK(function->CreationContext() == context);
17670 CheckContextId(function, 1);
17674 void HasOwnPropertyIndexedPropertyGetter(
17676 const v8::PropertyCallbackInfo<v8::Value>& info) {
17677 if (index == 42) info.GetReturnValue().Set(v8_str("yes"));
17681 void HasOwnPropertyNamedPropertyGetter(
17682 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
17683 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(v8_str("yes"));
17687 void HasOwnPropertyIndexedPropertyQuery(
17688 uint32_t index, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17689 if (index == 42) info.GetReturnValue().Set(1);
17693 void HasOwnPropertyNamedPropertyQuery(
17694 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17695 if (property->Equals(v8_str("foo"))) info.GetReturnValue().Set(1);
17699 void HasOwnPropertyNamedPropertyQuery2(
17700 Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) {
17701 if (property->Equals(v8_str("bar"))) info.GetReturnValue().Set(1);
17705 void HasOwnPropertyAccessorGetter(
17706 Local<String> property,
17707 const v8::PropertyCallbackInfo<v8::Value>& info) {
17708 info.GetReturnValue().Set(v8_str("yes"));
17712 TEST(HasOwnProperty) {
17714 v8::Isolate* isolate = env->GetIsolate();
17715 v8::HandleScope scope(isolate);
17716 { // Check normal properties and defined getters.
17717 Handle<Value> value = CompileRun(
17720 " this.__defineGetter__('baz', function() { return 1; });"
17722 "function Bar() { "
17724 " this.__defineGetter__('bla', function() { return 2; });"
17726 "Bar.prototype = new Foo();"
17728 CHECK(value->IsObject());
17729 Handle<Object> object = value->ToObject(isolate);
17730 CHECK(object->Has(v8_str("foo")));
17731 CHECK(!object->HasOwnProperty(v8_str("foo")));
17732 CHECK(object->HasOwnProperty(v8_str("bar")));
17733 CHECK(object->Has(v8_str("baz")));
17734 CHECK(!object->HasOwnProperty(v8_str("baz")));
17735 CHECK(object->HasOwnProperty(v8_str("bla")));
17737 { // Check named getter interceptors.
17738 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17739 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17740 HasOwnPropertyNamedPropertyGetter));
17741 Handle<Object> instance = templ->NewInstance();
17742 CHECK(!instance->HasOwnProperty(v8_str("42")));
17743 CHECK(instance->HasOwnProperty(v8_str("foo")));
17744 CHECK(!instance->HasOwnProperty(v8_str("bar")));
17746 { // Check indexed getter interceptors.
17747 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17748 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17749 HasOwnPropertyIndexedPropertyGetter));
17750 Handle<Object> instance = templ->NewInstance();
17751 CHECK(instance->HasOwnProperty(v8_str("42")));
17752 CHECK(!instance->HasOwnProperty(v8_str("43")));
17753 CHECK(!instance->HasOwnProperty(v8_str("foo")));
17755 { // Check named query interceptors.
17756 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17757 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17758 0, 0, HasOwnPropertyNamedPropertyQuery));
17759 Handle<Object> instance = templ->NewInstance();
17760 CHECK(instance->HasOwnProperty(v8_str("foo")));
17761 CHECK(!instance->HasOwnProperty(v8_str("bar")));
17763 { // Check indexed query interceptors.
17764 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17765 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17766 0, 0, HasOwnPropertyIndexedPropertyQuery));
17767 Handle<Object> instance = templ->NewInstance();
17768 CHECK(instance->HasOwnProperty(v8_str("42")));
17769 CHECK(!instance->HasOwnProperty(v8_str("41")));
17771 { // Check callbacks.
17772 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17773 templ->SetAccessor(v8_str("foo"), HasOwnPropertyAccessorGetter);
17774 Handle<Object> instance = templ->NewInstance();
17775 CHECK(instance->HasOwnProperty(v8_str("foo")));
17776 CHECK(!instance->HasOwnProperty(v8_str("bar")));
17778 { // Check that query wins on disagreement.
17779 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17780 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
17781 HasOwnPropertyNamedPropertyGetter, 0,
17782 HasOwnPropertyNamedPropertyQuery2));
17783 Handle<Object> instance = templ->NewInstance();
17784 CHECK(!instance->HasOwnProperty(v8_str("foo")));
17785 CHECK(instance->HasOwnProperty(v8_str("bar")));
17790 TEST(IndexedInterceptorWithStringProto) {
17791 v8::Isolate* isolate = CcTest::isolate();
17792 v8::HandleScope scope(isolate);
17793 Handle<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17794 templ->SetHandler(v8::IndexedPropertyHandlerConfiguration(
17795 NULL, NULL, HasOwnPropertyIndexedPropertyQuery));
17796 LocalContext context;
17797 context->Global()->Set(v8_str("obj"), templ->NewInstance());
17798 CompileRun("var s = new String('foobar'); obj.__proto__ = s;");
17799 // These should be intercepted.
17800 CHECK(CompileRun("42 in obj")->BooleanValue());
17801 CHECK(CompileRun("'42' in obj")->BooleanValue());
17802 // These should fall through to the String prototype.
17803 CHECK(CompileRun("0 in obj")->BooleanValue());
17804 CHECK(CompileRun("'0' in obj")->BooleanValue());
17805 // And these should both fail.
17806 CHECK(!CompileRun("32 in obj")->BooleanValue());
17807 CHECK(!CompileRun("'32' in obj")->BooleanValue());
17811 void CheckCodeGenerationAllowed() {
17812 Handle<Value> result = CompileRun("eval('42')");
17813 CHECK_EQ(42, result->Int32Value());
17814 result = CompileRun("(function(e) { return e('42'); })(eval)");
17815 CHECK_EQ(42, result->Int32Value());
17816 result = CompileRun("var f = new Function('return 42'); f()");
17817 CHECK_EQ(42, result->Int32Value());
17821 void CheckCodeGenerationDisallowed() {
17822 TryCatch try_catch(CcTest::isolate());
17824 Handle<Value> result = CompileRun("eval('42')");
17825 CHECK(result.IsEmpty());
17826 CHECK(try_catch.HasCaught());
17829 result = CompileRun("(function(e) { return e('42'); })(eval)");
17830 CHECK(result.IsEmpty());
17831 CHECK(try_catch.HasCaught());
17834 result = CompileRun("var f = new Function('return 42'); f()");
17835 CHECK(result.IsEmpty());
17836 CHECK(try_catch.HasCaught());
17840 bool CodeGenerationAllowed(Local<Context> context) {
17841 ApiTestFuzzer::Fuzz();
17846 bool CodeGenerationDisallowed(Local<Context> context) {
17847 ApiTestFuzzer::Fuzz();
17852 THREADED_TEST(AllowCodeGenFromStrings) {
17853 LocalContext context;
17854 v8::HandleScope scope(context->GetIsolate());
17856 // eval and the Function constructor allowed by default.
17857 CHECK(context->IsCodeGenerationFromStringsAllowed());
17858 CheckCodeGenerationAllowed();
17860 // Disallow eval and the Function constructor.
17861 context->AllowCodeGenerationFromStrings(false);
17862 CHECK(!context->IsCodeGenerationFromStringsAllowed());
17863 CheckCodeGenerationDisallowed();
17866 context->AllowCodeGenerationFromStrings(true);
17867 CheckCodeGenerationAllowed();
17869 // Disallow but setting a global callback that will allow the calls.
17870 context->AllowCodeGenerationFromStrings(false);
17871 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationAllowed);
17872 CHECK(!context->IsCodeGenerationFromStringsAllowed());
17873 CheckCodeGenerationAllowed();
17875 // Set a callback that disallows the code generation.
17876 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
17877 CHECK(!context->IsCodeGenerationFromStringsAllowed());
17878 CheckCodeGenerationDisallowed();
17882 TEST(SetErrorMessageForCodeGenFromStrings) {
17883 LocalContext context;
17884 v8::HandleScope scope(context->GetIsolate());
17885 TryCatch try_catch(context->GetIsolate());
17887 Handle<String> message = v8_str("Message") ;
17888 Handle<String> expected_message = v8_str("Uncaught EvalError: Message");
17889 V8::SetAllowCodeGenerationFromStringsCallback(&CodeGenerationDisallowed);
17890 context->AllowCodeGenerationFromStrings(false);
17891 context->SetErrorMessageForCodeGenerationFromStrings(message);
17892 Handle<Value> result = CompileRun("eval('42')");
17893 CHECK(result.IsEmpty());
17894 CHECK(try_catch.HasCaught());
17895 Handle<String> actual_message = try_catch.Message()->Get();
17896 CHECK(expected_message->Equals(actual_message));
17900 static void NonObjectThis(const v8::FunctionCallbackInfo<v8::Value>& args) {
17904 THREADED_TEST(CallAPIFunctionOnNonObject) {
17905 LocalContext context;
17906 v8::Isolate* isolate = context->GetIsolate();
17907 v8::HandleScope scope(isolate);
17908 Handle<FunctionTemplate> templ =
17909 v8::FunctionTemplate::New(isolate, NonObjectThis);
17910 Handle<Function> function = templ->GetFunction();
17911 context->Global()->Set(v8_str("f"), function);
17912 TryCatch try_catch(isolate);
17913 CompileRun("f.call(2)");
17917 // Regression test for issue 1470.
17918 THREADED_TEST(ReadOnlyIndexedProperties) {
17919 v8::Isolate* isolate = CcTest::isolate();
17920 v8::HandleScope scope(isolate);
17921 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
17923 LocalContext context;
17924 Local<v8::Object> obj = templ->NewInstance();
17925 context->Global()->Set(v8_str("obj"), obj);
17926 obj->ForceSet(v8_str("1"), v8_str("DONT_CHANGE"), v8::ReadOnly);
17927 obj->Set(v8_str("1"), v8_str("foobar"));
17928 CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("1"))));
17929 obj->ForceSet(v8_num(2), v8_str("DONT_CHANGE"), v8::ReadOnly);
17930 obj->Set(v8_num(2), v8_str("foobar"));
17931 CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_num(2))));
17933 // Test non-smi case.
17934 obj->ForceSet(v8_str("2000000000"), v8_str("DONT_CHANGE"), v8::ReadOnly);
17935 obj->Set(v8_str("2000000000"), v8_str("foobar"));
17936 CHECK(v8_str("DONT_CHANGE")->Equals(obj->Get(v8_str("2000000000"))));
17940 static int CountLiveMapsInMapCache(i::Context* context) {
17941 i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache());
17942 int length = map_cache->length();
17944 for (int i = 0; i < length; i++) {
17945 i::Object* value = map_cache->get(i);
17946 if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++;
17952 THREADED_TEST(Regress1516) {
17953 LocalContext context;
17954 v8::HandleScope scope(context->GetIsolate());
17956 // Object with 20 properties is not a common case, so it should be removed
17957 // from the cache after GC.
17958 { v8::HandleScope temp_scope(context->GetIsolate());
17961 "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, "
17962 "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, "
17963 "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, "
17964 "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, "
17968 int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context());
17969 CHECK_LE(1, elements);
17971 CcTest::heap()->CollectAllGarbage();
17973 CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context()));
17977 THREADED_TEST(Regress93759) {
17978 v8::Isolate* isolate = CcTest::isolate();
17979 HandleScope scope(isolate);
17981 // Template for object with security check.
17982 Local<ObjectTemplate> no_proto_template = v8::ObjectTemplate::New(isolate);
17983 no_proto_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
17985 // Templates for objects with hidden prototypes and possibly security check.
17986 Local<FunctionTemplate> hidden_proto_template =
17987 v8::FunctionTemplate::New(isolate);
17988 hidden_proto_template->SetHiddenPrototype(true);
17990 Local<FunctionTemplate> protected_hidden_proto_template =
17991 v8::FunctionTemplate::New(isolate);
17992 protected_hidden_proto_template->InstanceTemplate()->SetAccessCheckCallbacks(
17993 AccessAlwaysBlocked, NULL);
17994 protected_hidden_proto_template->SetHiddenPrototype(true);
17996 // Context for "foreign" objects used in test.
17997 Local<Context> context = v8::Context::New(isolate);
18000 // Plain object, no security check.
18001 Local<Object> simple_object = Object::New(isolate);
18003 // Object with explicit security check.
18004 Local<Object> protected_object = no_proto_template->NewInstance();
18006 // JSGlobalProxy object, always have security check.
18007 Local<Object> proxy_object = context->Global();
18009 // Global object, the prototype of proxy_object. No security checks.
18010 Local<Object> global_object = proxy_object->GetPrototype()->ToObject(isolate);
18012 // Hidden prototype without security check.
18013 Local<Object> hidden_prototype =
18014 hidden_proto_template->GetFunction()->NewInstance();
18015 Local<Object> object_with_hidden =
18016 Object::New(isolate);
18017 object_with_hidden->SetPrototype(hidden_prototype);
18019 // Hidden prototype with security check on the hidden prototype.
18020 Local<Object> protected_hidden_prototype =
18021 protected_hidden_proto_template->GetFunction()->NewInstance();
18022 Local<Object> object_with_protected_hidden =
18023 Object::New(isolate);
18024 object_with_protected_hidden->SetPrototype(protected_hidden_prototype);
18028 // Template for object for second context. Values to test are put on it as
18030 Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
18031 global_template->Set(v8_str("simple"), simple_object);
18032 global_template->Set(v8_str("protected"), protected_object);
18033 global_template->Set(v8_str("global"), global_object);
18034 global_template->Set(v8_str("proxy"), proxy_object);
18035 global_template->Set(v8_str("hidden"), object_with_hidden);
18036 global_template->Set(v8_str("phidden"), object_with_protected_hidden);
18038 LocalContext context2(NULL, global_template);
18040 Local<Value> result1 = CompileRun("Object.getPrototypeOf(simple)");
18041 CHECK(result1->Equals(simple_object->GetPrototype()));
18043 Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
18044 CHECK(result2->IsNull());
18046 Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
18047 CHECK(result3->Equals(global_object->GetPrototype()));
18049 Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
18050 CHECK(result4->IsNull());
18052 Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
18053 CHECK(result5->Equals(
18054 object_with_hidden->GetPrototype()->ToObject(isolate)->GetPrototype()));
18056 Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
18057 CHECK(result6->IsNull());
18061 static void TestReceiver(Local<Value> expected_result,
18062 Local<Value> expected_receiver,
18063 const char* code) {
18064 Local<Value> result = CompileRun(code);
18065 CHECK(result->IsObject());
18066 CHECK(expected_receiver->Equals(result.As<v8::Object>()->Get(1)));
18067 CHECK(expected_result->Equals(result.As<v8::Object>()->Get(0)));
18071 THREADED_TEST(ForeignFunctionReceiver) {
18072 v8::Isolate* isolate = CcTest::isolate();
18073 HandleScope scope(isolate);
18075 // Create two contexts with different "id" properties ('i' and 'o').
18076 // Call a function both from its own context and from a the foreign
18077 // context, and see what "this" is bound to (returning both "this"
18078 // and "this.id" for comparison).
18080 Local<Context> foreign_context = v8::Context::New(isolate);
18081 foreign_context->Enter();
18082 Local<Value> foreign_function =
18083 CompileRun("function func() { return { 0: this.id, "
18085 " toString: function() { "
18092 CHECK(foreign_function->IsFunction());
18093 foreign_context->Exit();
18095 LocalContext context;
18097 Local<String> password = v8_str("Password");
18098 // Don't get hit by security checks when accessing foreign_context's
18099 // global receiver (aka. global proxy).
18100 context->SetSecurityToken(password);
18101 foreign_context->SetSecurityToken(password);
18103 Local<String> i = v8_str("i");
18104 Local<String> o = v8_str("o");
18105 Local<String> id = v8_str("id");
18107 CompileRun("function ownfunc() { return { 0: this.id, "
18109 " toString: function() { "
18116 context->Global()->Set(v8_str("func"), foreign_function);
18118 // Sanity check the contexts.
18119 CHECK(i->Equals(foreign_context->Global()->Get(id)));
18120 CHECK(o->Equals(context->Global()->Get(id)));
18122 // Checking local function's receiver.
18123 // Calling function using its call/apply methods.
18124 TestReceiver(o, context->Global(), "ownfunc.call()");
18125 TestReceiver(o, context->Global(), "ownfunc.apply()");
18126 // Making calls through built-in functions.
18127 TestReceiver(o, context->Global(), "[1].map(ownfunc)[0]");
18128 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/,ownfunc)[1]")));
18129 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[1]")));
18130 CHECK(o->Equals(CompileRun("'abcbd'.replace(/b/g,ownfunc)[3]")));
18131 // Calling with environment record as base.
18132 TestReceiver(o, context->Global(), "ownfunc()");
18133 // Calling with no base.
18134 TestReceiver(o, context->Global(), "(1,ownfunc)()");
18136 // Checking foreign function return value.
18137 // Calling function using its call/apply methods.
18138 TestReceiver(i, foreign_context->Global(), "func.call()");
18139 TestReceiver(i, foreign_context->Global(), "func.apply()");
18140 // Calling function using another context's call/apply methods.
18141 TestReceiver(i, foreign_context->Global(),
18142 "Function.prototype.call.call(func)");
18143 TestReceiver(i, foreign_context->Global(),
18144 "Function.prototype.call.apply(func)");
18145 TestReceiver(i, foreign_context->Global(),
18146 "Function.prototype.apply.call(func)");
18147 TestReceiver(i, foreign_context->Global(),
18148 "Function.prototype.apply.apply(func)");
18149 // Making calls through built-in functions.
18150 TestReceiver(i, foreign_context->Global(), "[1].map(func)[0]");
18151 // ToString(func()) is func()[0], i.e., the returned this.id.
18152 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/,func)[1]")));
18153 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[1]")));
18154 CHECK(i->Equals(CompileRun("'abcbd'.replace(/b/g,func)[3]")));
18156 // Calling with environment record as base.
18157 TestReceiver(i, foreign_context->Global(), "func()");
18158 // Calling with no base.
18159 TestReceiver(i, foreign_context->Global(), "(1,func)()");
18163 uint8_t callback_fired = 0;
18166 void CallCompletedCallback1() {
18167 v8::base::OS::Print("Firing callback 1.\n");
18168 callback_fired ^= 1; // Toggle first bit.
18172 void CallCompletedCallback2() {
18173 v8::base::OS::Print("Firing callback 2.\n");
18174 callback_fired ^= 2; // Toggle second bit.
18178 void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
18179 int32_t level = args[0]->Int32Value();
18182 v8::base::OS::Print("Entering recursion level %d.\n", level);
18184 i::Vector<char> script_vector(script, sizeof(script));
18185 i::SNPrintF(script_vector, "recursion(%d)", level);
18186 CompileRun(script_vector.start());
18187 v8::base::OS::Print("Leaving recursion level %d.\n", level);
18188 CHECK_EQ(0, callback_fired);
18190 v8::base::OS::Print("Recursion ends.\n");
18191 CHECK_EQ(0, callback_fired);
18196 TEST(CallCompletedCallback) {
18198 v8::HandleScope scope(env->GetIsolate());
18199 v8::Handle<v8::FunctionTemplate> recursive_runtime =
18200 v8::FunctionTemplate::New(env->GetIsolate(), RecursiveCall);
18201 env->Global()->Set(v8_str("recursion"),
18202 recursive_runtime->GetFunction());
18203 // Adding the same callback a second time has no effect.
18204 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18205 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
18206 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
18207 v8::base::OS::Print("--- Script (1) ---\n");
18208 Local<Script> script = v8::Script::Compile(
18209 v8::String::NewFromUtf8(env->GetIsolate(), "recursion(0)"));
18211 CHECK_EQ(3, callback_fired);
18213 v8::base::OS::Print("\n--- Script (2) ---\n");
18214 callback_fired = 0;
18215 env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
18217 CHECK_EQ(2, callback_fired);
18219 v8::base::OS::Print("\n--- Function ---\n");
18220 callback_fired = 0;
18221 Local<Function> recursive_function =
18222 Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
18223 v8::Handle<Value> args[] = { v8_num(0) };
18224 recursive_function->Call(env->Global(), 1, args);
18225 CHECK_EQ(2, callback_fired);
18229 void CallCompletedCallbackNoException() {
18230 v8::HandleScope scope(CcTest::isolate());
18231 CompileRun("1+1;");
18235 void CallCompletedCallbackException() {
18236 v8::HandleScope scope(CcTest::isolate());
18237 CompileRun("throw 'second exception';");
18241 TEST(CallCompletedCallbackOneException) {
18243 v8::HandleScope scope(env->GetIsolate());
18244 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackNoException);
18245 CompileRun("throw 'exception';");
18249 TEST(CallCompletedCallbackTwoExceptions) {
18251 v8::HandleScope scope(env->GetIsolate());
18252 env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallbackException);
18253 CompileRun("throw 'first exception';");
18257 static void MicrotaskOne(const v8::FunctionCallbackInfo<Value>& info) {
18258 v8::HandleScope scope(info.GetIsolate());
18259 CompileRun("ext1Calls++;");
18263 static void MicrotaskTwo(const v8::FunctionCallbackInfo<Value>& info) {
18264 v8::HandleScope scope(info.GetIsolate());
18265 CompileRun("ext2Calls++;");
18269 void* g_passed_to_three = NULL;
18272 static void MicrotaskThree(void* data) {
18273 g_passed_to_three = data;
18277 TEST(EnqueueMicrotask) {
18279 v8::HandleScope scope(env->GetIsolate());
18281 "var ext1Calls = 0;"
18282 "var ext2Calls = 0;");
18283 CompileRun("1+1;");
18284 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
18285 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18287 env->GetIsolate()->EnqueueMicrotask(
18288 Function::New(env->GetIsolate(), MicrotaskOne));
18289 CompileRun("1+1;");
18290 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18291 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18293 env->GetIsolate()->EnqueueMicrotask(
18294 Function::New(env->GetIsolate(), MicrotaskOne));
18295 env->GetIsolate()->EnqueueMicrotask(
18296 Function::New(env->GetIsolate(), MicrotaskTwo));
18297 CompileRun("1+1;");
18298 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18299 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18301 env->GetIsolate()->EnqueueMicrotask(
18302 Function::New(env->GetIsolate(), MicrotaskTwo));
18303 CompileRun("1+1;");
18304 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18305 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18307 CompileRun("1+1;");
18308 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18309 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18311 g_passed_to_three = NULL;
18312 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree);
18313 CompileRun("1+1;");
18314 CHECK(!g_passed_to_three);
18315 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18316 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18319 env->GetIsolate()->EnqueueMicrotask(
18320 Function::New(env->GetIsolate(), MicrotaskOne));
18321 env->GetIsolate()->EnqueueMicrotask(MicrotaskThree, &dummy);
18322 env->GetIsolate()->EnqueueMicrotask(
18323 Function::New(env->GetIsolate(), MicrotaskTwo));
18324 CompileRun("1+1;");
18325 CHECK_EQ(&dummy, g_passed_to_three);
18326 CHECK_EQ(3, CompileRun("ext1Calls")->Int32Value());
18327 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18328 g_passed_to_three = NULL;
18332 static void MicrotaskExceptionOne(
18333 const v8::FunctionCallbackInfo<Value>& info) {
18334 v8::HandleScope scope(info.GetIsolate());
18335 CompileRun("exception1Calls++;");
18336 info.GetIsolate()->ThrowException(
18337 v8::Exception::Error(v8_str("first")));
18341 static void MicrotaskExceptionTwo(
18342 const v8::FunctionCallbackInfo<Value>& info) {
18343 v8::HandleScope scope(info.GetIsolate());
18344 CompileRun("exception2Calls++;");
18345 info.GetIsolate()->ThrowException(
18346 v8::Exception::Error(v8_str("second")));
18350 TEST(RunMicrotasksIgnoresThrownExceptions) {
18352 v8::Isolate* isolate = env->GetIsolate();
18353 v8::HandleScope scope(isolate);
18355 "var exception1Calls = 0;"
18356 "var exception2Calls = 0;");
18357 isolate->EnqueueMicrotask(
18358 Function::New(isolate, MicrotaskExceptionOne));
18359 isolate->EnqueueMicrotask(
18360 Function::New(isolate, MicrotaskExceptionTwo));
18361 TryCatch try_catch(isolate);
18362 CompileRun("1+1;");
18363 CHECK(!try_catch.HasCaught());
18364 CHECK_EQ(1, CompileRun("exception1Calls")->Int32Value());
18365 CHECK_EQ(1, CompileRun("exception2Calls")->Int32Value());
18369 TEST(SetAutorunMicrotasks) {
18371 v8::HandleScope scope(env->GetIsolate());
18373 "var ext1Calls = 0;"
18374 "var ext2Calls = 0;");
18375 CompileRun("1+1;");
18376 CHECK_EQ(0, CompileRun("ext1Calls")->Int32Value());
18377 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18379 env->GetIsolate()->EnqueueMicrotask(
18380 Function::New(env->GetIsolate(), MicrotaskOne));
18381 CompileRun("1+1;");
18382 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18383 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18385 env->GetIsolate()->SetAutorunMicrotasks(false);
18386 env->GetIsolate()->EnqueueMicrotask(
18387 Function::New(env->GetIsolate(), MicrotaskOne));
18388 env->GetIsolate()->EnqueueMicrotask(
18389 Function::New(env->GetIsolate(), MicrotaskTwo));
18390 CompileRun("1+1;");
18391 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18392 CHECK_EQ(0, CompileRun("ext2Calls")->Int32Value());
18394 env->GetIsolate()->RunMicrotasks();
18395 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18396 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18398 env->GetIsolate()->EnqueueMicrotask(
18399 Function::New(env->GetIsolate(), MicrotaskTwo));
18400 CompileRun("1+1;");
18401 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18402 CHECK_EQ(1, CompileRun("ext2Calls")->Int32Value());
18404 env->GetIsolate()->RunMicrotasks();
18405 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18406 CHECK_EQ(2, CompileRun("ext2Calls")->Int32Value());
18408 env->GetIsolate()->SetAutorunMicrotasks(true);
18409 env->GetIsolate()->EnqueueMicrotask(
18410 Function::New(env->GetIsolate(), MicrotaskTwo));
18411 CompileRun("1+1;");
18412 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18413 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18415 env->GetIsolate()->EnqueueMicrotask(
18416 Function::New(env->GetIsolate(), MicrotaskTwo));
18418 v8::Isolate::SuppressMicrotaskExecutionScope scope(env->GetIsolate());
18419 CompileRun("1+1;");
18420 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18421 CHECK_EQ(3, CompileRun("ext2Calls")->Int32Value());
18424 CompileRun("1+1;");
18425 CHECK_EQ(2, CompileRun("ext1Calls")->Int32Value());
18426 CHECK_EQ(4, CompileRun("ext2Calls")->Int32Value());
18430 TEST(RunMicrotasksWithoutEnteringContext) {
18431 v8::Isolate* isolate = CcTest::isolate();
18432 HandleScope handle_scope(isolate);
18433 isolate->SetAutorunMicrotasks(false);
18434 Handle<Context> context = Context::New(isolate);
18436 Context::Scope context_scope(context);
18437 CompileRun("var ext1Calls = 0;");
18438 isolate->EnqueueMicrotask(Function::New(isolate, MicrotaskOne));
18440 isolate->RunMicrotasks();
18442 Context::Scope context_scope(context);
18443 CHECK_EQ(1, CompileRun("ext1Calls")->Int32Value());
18445 isolate->SetAutorunMicrotasks(true);
18449 static void DebugEventInObserver(const v8::Debug::EventDetails& event_details) {
18450 v8::DebugEvent event = event_details.GetEvent();
18451 if (event != v8::Break) return;
18452 Handle<Object> exec_state = event_details.GetExecutionState();
18453 Handle<Value> break_id = exec_state->Get(v8_str("break_id"));
18454 CompileRun("function f(id) { new FrameDetails(id, 0); }");
18455 Handle<Function> fun =
18456 Handle<Function>::Cast(CcTest::global()->Get(v8_str("f")));
18457 fun->Call(CcTest::global(), 1, &break_id);
18461 TEST(Regress385349) {
18462 i::FLAG_allow_natives_syntax = true;
18463 v8::Isolate* isolate = CcTest::isolate();
18464 HandleScope handle_scope(isolate);
18465 isolate->SetAutorunMicrotasks(false);
18466 Handle<Context> context = Context::New(isolate);
18467 v8::Debug::SetDebugEventListener(DebugEventInObserver);
18469 Context::Scope context_scope(context);
18470 CompileRun("var obj = {};"
18471 "Object.observe(obj, function(changes) { debugger; });"
18474 isolate->RunMicrotasks();
18475 isolate->SetAutorunMicrotasks(true);
18476 v8::Debug::SetDebugEventListener(NULL);
18480 #ifdef ENABLE_DISASSEMBLER
18481 static int probes_counter = 0;
18482 static int misses_counter = 0;
18483 static int updates_counter = 0;
18486 static int* LookupCounter(const char* name) {
18487 if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
18488 return &probes_counter;
18489 } else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
18490 return &misses_counter;
18491 } else if (strcmp(name, "c:V8.MegamorphicStubCacheUpdates") == 0) {
18492 return &updates_counter;
18498 static const char* kMegamorphicTestProgram =
18499 "function ClassA() { };"
18500 "function ClassB() { };"
18501 "ClassA.prototype.foo = function() { };"
18502 "ClassB.prototype.foo = function() { };"
18503 "function fooify(obj) { obj.foo(); };"
18504 "var a = new ClassA();"
18505 "var b = new ClassB();"
18506 "for (var i = 0; i < 10000; i++) {"
18513 static void StubCacheHelper(bool primary) {
18514 #ifdef ENABLE_DISASSEMBLER
18515 i::FLAG_native_code_counters = true;
18517 i::FLAG_test_primary_stub_cache = true;
18519 i::FLAG_test_secondary_stub_cache = true;
18521 i::FLAG_crankshaft = false;
18523 env->GetIsolate()->SetCounterFunction(LookupCounter);
18524 v8::HandleScope scope(env->GetIsolate());
18525 int initial_probes = probes_counter;
18526 int initial_misses = misses_counter;
18527 int initial_updates = updates_counter;
18528 CompileRun(kMegamorphicTestProgram);
18529 int probes = probes_counter - initial_probes;
18530 int misses = misses_counter - initial_misses;
18531 int updates = updates_counter - initial_updates;
18532 CHECK_LT(updates, 10);
18533 CHECK_LT(misses, 10);
18534 // TODO(verwaest): Update this test to overflow the degree of polymorphism
18535 // before megamorphism. The number of probes will only work once we teach the
18536 // serializer to embed references to counters in the stubs, given that the
18537 // megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
18538 CHECK_GE(probes, 0);
18543 TEST(SecondaryStubCache) {
18544 StubCacheHelper(true);
18548 TEST(PrimaryStubCache) {
18549 StubCacheHelper(false);
18554 static int cow_arrays_created_runtime = 0;
18557 static int* LookupCounterCOWArrays(const char* name) {
18558 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) {
18559 return &cow_arrays_created_runtime;
18566 TEST(CheckCOWArraysCreatedRuntimeCounter) {
18568 i::FLAG_native_code_counters = true;
18570 env->GetIsolate()->SetCounterFunction(LookupCounterCOWArrays);
18571 v8::HandleScope scope(env->GetIsolate());
18572 int initial_cow_arrays = cow_arrays_created_runtime;
18573 CompileRun("var o = [1, 2, 3];");
18574 CHECK_EQ(1, cow_arrays_created_runtime - initial_cow_arrays);
18575 CompileRun("var o = {foo: [4, 5, 6], bar: [3, 0]};");
18576 CHECK_EQ(3, cow_arrays_created_runtime - initial_cow_arrays);
18577 CompileRun("var o = {foo: [1, 2, 3, [4, 5, 6]], bar: 'hi'};");
18578 CHECK_EQ(4, cow_arrays_created_runtime - initial_cow_arrays);
18583 TEST(StaticGetters) {
18584 LocalContext context;
18585 i::Factory* factory = CcTest::i_isolate()->factory();
18586 v8::Isolate* isolate = CcTest::isolate();
18587 v8::HandleScope scope(isolate);
18588 i::Handle<i::Object> undefined_value = factory->undefined_value();
18589 CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
18590 i::Handle<i::Object> null_value = factory->null_value();
18591 CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
18592 i::Handle<i::Object> true_value = factory->true_value();
18593 CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
18594 i::Handle<i::Object> false_value = factory->false_value();
18595 CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
18599 UNINITIALIZED_TEST(IsolateEmbedderData) {
18600 CcTest::DisableAutomaticDispose();
18601 v8::Isolate::CreateParams create_params;
18602 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
18603 v8::Isolate* isolate = v8::Isolate::New(create_params);
18605 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
18606 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18607 CHECK(!isolate->GetData(slot));
18608 CHECK(!i_isolate->GetData(slot));
18610 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18611 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
18612 isolate->SetData(slot, data);
18614 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18615 void* data = reinterpret_cast<void*>(0xacce55ed + slot);
18616 CHECK_EQ(data, isolate->GetData(slot));
18617 CHECK_EQ(data, i_isolate->GetData(slot));
18619 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18620 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
18621 isolate->SetData(slot, data);
18623 for (uint32_t slot = 0; slot < v8::Isolate::GetNumberOfDataSlots(); ++slot) {
18624 void* data = reinterpret_cast<void*>(0xdecea5ed + slot);
18625 CHECK_EQ(data, isolate->GetData(slot));
18626 CHECK_EQ(data, i_isolate->GetData(slot));
18629 isolate->Dispose();
18633 TEST(StringEmpty) {
18634 LocalContext context;
18635 i::Factory* factory = CcTest::i_isolate()->factory();
18636 v8::Isolate* isolate = CcTest::isolate();
18637 v8::HandleScope scope(isolate);
18638 i::Handle<i::Object> empty_string = factory->empty_string();
18639 CHECK(*v8::Utils::OpenHandle(*v8::String::Empty(isolate)) == *empty_string);
18643 static int instance_checked_getter_count = 0;
18644 static void InstanceCheckedGetter(
18645 Local<String> name,
18646 const v8::PropertyCallbackInfo<v8::Value>& info) {
18647 CHECK(name->Equals(v8_str("foo")));
18648 instance_checked_getter_count++;
18649 info.GetReturnValue().Set(v8_num(11));
18653 static int instance_checked_setter_count = 0;
18654 static void InstanceCheckedSetter(Local<String> name,
18655 Local<Value> value,
18656 const v8::PropertyCallbackInfo<void>& info) {
18657 CHECK(name->Equals(v8_str("foo")));
18658 CHECK(value->Equals(v8_num(23)));
18659 instance_checked_setter_count++;
18663 static void CheckInstanceCheckedResult(int getters, int setters,
18664 bool expects_callbacks,
18665 TryCatch* try_catch) {
18666 if (expects_callbacks) {
18667 CHECK(!try_catch->HasCaught());
18668 CHECK_EQ(getters, instance_checked_getter_count);
18669 CHECK_EQ(setters, instance_checked_setter_count);
18671 CHECK(try_catch->HasCaught());
18672 CHECK_EQ(0, instance_checked_getter_count);
18673 CHECK_EQ(0, instance_checked_setter_count);
18675 try_catch->Reset();
18679 static void CheckInstanceCheckedAccessors(bool expects_callbacks) {
18680 instance_checked_getter_count = 0;
18681 instance_checked_setter_count = 0;
18682 TryCatch try_catch(CcTest::isolate());
18684 // Test path through generic runtime code.
18685 CompileRun("obj.foo");
18686 CheckInstanceCheckedResult(1, 0, expects_callbacks, &try_catch);
18687 CompileRun("obj.foo = 23");
18688 CheckInstanceCheckedResult(1, 1, expects_callbacks, &try_catch);
18690 // Test path through generated LoadIC and StoredIC.
18691 CompileRun("function test_get(o) { o.foo; }"
18693 CheckInstanceCheckedResult(2, 1, expects_callbacks, &try_catch);
18694 CompileRun("test_get(obj);");
18695 CheckInstanceCheckedResult(3, 1, expects_callbacks, &try_catch);
18696 CompileRun("test_get(obj);");
18697 CheckInstanceCheckedResult(4, 1, expects_callbacks, &try_catch);
18698 CompileRun("function test_set(o) { o.foo = 23; }"
18700 CheckInstanceCheckedResult(4, 2, expects_callbacks, &try_catch);
18701 CompileRun("test_set(obj);");
18702 CheckInstanceCheckedResult(4, 3, expects_callbacks, &try_catch);
18703 CompileRun("test_set(obj);");
18704 CheckInstanceCheckedResult(4, 4, expects_callbacks, &try_catch);
18706 // Test path through optimized code.
18707 CompileRun("%OptimizeFunctionOnNextCall(test_get);"
18709 CheckInstanceCheckedResult(5, 4, expects_callbacks, &try_catch);
18710 CompileRun("%OptimizeFunctionOnNextCall(test_set);"
18712 CheckInstanceCheckedResult(5, 5, expects_callbacks, &try_catch);
18714 // Cleanup so that closures start out fresh in next check.
18715 CompileRun("%DeoptimizeFunction(test_get);"
18716 "%ClearFunctionTypeFeedback(test_get);"
18717 "%DeoptimizeFunction(test_set);"
18718 "%ClearFunctionTypeFeedback(test_set);");
18722 THREADED_TEST(InstanceCheckOnInstanceAccessor) {
18723 v8::internal::FLAG_allow_natives_syntax = true;
18724 LocalContext context;
18725 v8::HandleScope scope(context->GetIsolate());
18727 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18728 Local<ObjectTemplate> inst = templ->InstanceTemplate();
18729 inst->SetAccessor(v8_str("foo"),
18730 InstanceCheckedGetter, InstanceCheckedSetter,
18734 v8::AccessorSignature::New(context->GetIsolate(), templ));
18735 context->Global()->Set(v8_str("f"), templ->GetFunction());
18737 printf("Testing positive ...\n");
18738 CompileRun("var obj = new f();");
18739 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18740 CheckInstanceCheckedAccessors(true);
18742 printf("Testing negative ...\n");
18743 CompileRun("var obj = {};"
18744 "obj.__proto__ = new f();");
18745 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18746 CheckInstanceCheckedAccessors(false);
18750 static void EmptyInterceptorGetter(
18751 Local<String> name, const v8::PropertyCallbackInfo<v8::Value>& info) {}
18754 static void EmptyInterceptorSetter(
18755 Local<String> name, Local<Value> value,
18756 const v8::PropertyCallbackInfo<v8::Value>& info) {}
18759 THREADED_TEST(InstanceCheckOnInstanceAccessorWithInterceptor) {
18760 v8::internal::FLAG_allow_natives_syntax = true;
18761 LocalContext context;
18762 v8::HandleScope scope(context->GetIsolate());
18764 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18765 Local<ObjectTemplate> inst = templ->InstanceTemplate();
18766 templ->InstanceTemplate()->SetNamedPropertyHandler(EmptyInterceptorGetter,
18767 EmptyInterceptorSetter);
18768 inst->SetAccessor(v8_str("foo"),
18769 InstanceCheckedGetter, InstanceCheckedSetter,
18773 v8::AccessorSignature::New(context->GetIsolate(), templ));
18774 context->Global()->Set(v8_str("f"), templ->GetFunction());
18776 printf("Testing positive ...\n");
18777 CompileRun("var obj = new f();");
18778 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18779 CheckInstanceCheckedAccessors(true);
18781 printf("Testing negative ...\n");
18782 CompileRun("var obj = {};"
18783 "obj.__proto__ = new f();");
18784 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18785 CheckInstanceCheckedAccessors(false);
18789 THREADED_TEST(InstanceCheckOnPrototypeAccessor) {
18790 v8::internal::FLAG_allow_natives_syntax = true;
18791 LocalContext context;
18792 v8::HandleScope scope(context->GetIsolate());
18794 Local<FunctionTemplate> templ = FunctionTemplate::New(context->GetIsolate());
18795 Local<ObjectTemplate> proto = templ->PrototypeTemplate();
18796 proto->SetAccessor(v8_str("foo"), InstanceCheckedGetter,
18797 InstanceCheckedSetter, Handle<Value>(), v8::DEFAULT,
18799 v8::AccessorSignature::New(context->GetIsolate(), templ));
18800 context->Global()->Set(v8_str("f"), templ->GetFunction());
18802 printf("Testing positive ...\n");
18803 CompileRun("var obj = new f();");
18804 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18805 CheckInstanceCheckedAccessors(true);
18807 printf("Testing negative ...\n");
18808 CompileRun("var obj = {};"
18809 "obj.__proto__ = new f();");
18810 CHECK(!templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18811 CheckInstanceCheckedAccessors(false);
18813 printf("Testing positive with modified prototype chain ...\n");
18814 CompileRun("var obj = new f();"
18816 "pro.__proto__ = obj.__proto__;"
18817 "obj.__proto__ = pro;");
18818 CHECK(templ->HasInstance(context->Global()->Get(v8_str("obj"))));
18819 CheckInstanceCheckedAccessors(true);
18823 TEST(TryFinallyMessage) {
18824 LocalContext context;
18825 v8::HandleScope scope(context->GetIsolate());
18827 // Test that the original error message is not lost if there is a
18828 // recursive call into Javascript is done in the finally block, e.g. to
18829 // initialize an IC. (crbug.com/129171)
18830 TryCatch try_catch(context->GetIsolate());
18831 const char* trigger_ic =
18833 " throw new Error('test'); \n"
18836 " x++; \n" // Trigger an IC initialization here.
18838 CompileRun(trigger_ic);
18839 CHECK(try_catch.HasCaught());
18840 Local<Message> message = try_catch.Message();
18841 CHECK(!message.IsEmpty());
18842 CHECK_EQ(2, message->GetLineNumber());
18846 // Test that the original exception message is indeed overwritten if
18847 // a new error is thrown in the finally block.
18848 TryCatch try_catch(context->GetIsolate());
18849 const char* throw_again =
18851 " throw new Error('test'); \n"
18855 " throw new Error('again'); \n" // This is the new uncaught error.
18857 CompileRun(throw_again);
18858 CHECK(try_catch.HasCaught());
18859 Local<Message> message = try_catch.Message();
18860 CHECK(!message.IsEmpty());
18861 CHECK_EQ(6, message->GetLineNumber());
18866 static void Helper137002(bool do_store,
18868 bool remove_accessor,
18869 bool interceptor) {
18870 LocalContext context;
18871 Local<ObjectTemplate> templ = ObjectTemplate::New(context->GetIsolate());
18873 templ->SetHandler(v8::NamedPropertyHandlerConfiguration(FooGetInterceptor,
18874 FooSetInterceptor));
18876 templ->SetAccessor(v8_str("foo"),
18877 GetterWhichReturns42,
18878 SetterWhichSetsYOnThisTo23);
18880 context->Global()->Set(v8_str("obj"), templ->NewInstance());
18882 // Turn monomorphic on slow object with native accessor, then turn
18883 // polymorphic, finally optimize to create negative lookup and fail.
18884 CompileRun(do_store ?
18885 "function f(x) { x.foo = void 0; }" :
18886 "function f(x) { return x.foo; }");
18887 CompileRun("obj.y = void 0;");
18888 if (!interceptor) {
18889 CompileRun("%OptimizeObjectForAddingMultipleProperties(obj, 1);");
18891 CompileRun("obj.__proto__ = null;"
18892 "f(obj); f(obj); f(obj);");
18894 CompileRun("f({});");
18896 CompileRun("obj.y = void 0;"
18897 "%OptimizeFunctionOnNextCall(f);");
18898 if (remove_accessor) {
18899 CompileRun("delete obj.foo;");
18901 CompileRun("var result = f(obj);");
18903 CompileRun("result = obj.y;");
18905 if (remove_accessor && !interceptor) {
18906 CHECK(context->Global()->Get(v8_str("result"))->IsUndefined());
18908 CHECK_EQ(do_store ? 23 : 42,
18909 context->Global()->Get(v8_str("result"))->Int32Value());
18914 THREADED_TEST(Regress137002a) {
18915 i::FLAG_allow_natives_syntax = true;
18916 i::FLAG_compilation_cache = false;
18917 v8::HandleScope scope(CcTest::isolate());
18918 for (int i = 0; i < 16; i++) {
18919 Helper137002(i & 8, i & 4, i & 2, i & 1);
18924 THREADED_TEST(Regress137002b) {
18925 i::FLAG_allow_natives_syntax = true;
18926 LocalContext context;
18927 v8::Isolate* isolate = context->GetIsolate();
18928 v8::HandleScope scope(isolate);
18929 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18930 templ->SetAccessor(v8_str("foo"),
18931 GetterWhichReturns42,
18932 SetterWhichSetsYOnThisTo23);
18933 context->Global()->Set(v8_str("obj"), templ->NewInstance());
18935 // Turn monomorphic on slow object with native accessor, then just
18936 // delete the property and fail.
18937 CompileRun("function load(x) { return x.foo; }"
18938 "function store(x) { x.foo = void 0; }"
18939 "function keyed_load(x, key) { return x[key]; }"
18940 // Second version of function has a different source (add void 0)
18941 // so that it does not share code with the first version. This
18942 // ensures that the ICs are monomorphic.
18943 "function load2(x) { void 0; return x.foo; }"
18944 "function store2(x) { void 0; x.foo = void 0; }"
18945 "function keyed_load2(x, key) { void 0; return x[key]; }"
18948 "obj.__proto__ = null;"
18950 "subobj.y = void 0;"
18951 "subobj.__proto__ = obj;"
18952 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
18954 // Make the ICs monomorphic.
18955 "load(obj); load(obj);"
18956 "load2(subobj); load2(subobj);"
18957 "store(obj); store(obj);"
18958 "store2(subobj); store2(subobj);"
18959 "keyed_load(obj, 'foo'); keyed_load(obj, 'foo');"
18960 "keyed_load2(subobj, 'foo'); keyed_load2(subobj, 'foo');"
18962 // Actually test the shiny new ICs and better not crash. This
18963 // serves as a regression test for issue 142088 as well.
18968 "keyed_load(obj, 'foo');"
18969 "keyed_load2(subobj, 'foo');"
18971 // Delete the accessor. It better not be called any more now.
18974 "subobj.y = void 0;"
18976 "var load_result = load(obj);"
18977 "var load_result2 = load2(subobj);"
18978 "var keyed_load_result = keyed_load(obj, 'foo');"
18979 "var keyed_load_result2 = keyed_load2(subobj, 'foo');"
18982 "var y_from_obj = obj.y;"
18983 "var y_from_subobj = subobj.y;");
18984 CHECK(context->Global()->Get(v8_str("load_result"))->IsUndefined());
18985 CHECK(context->Global()->Get(v8_str("load_result2"))->IsUndefined());
18986 CHECK(context->Global()->Get(v8_str("keyed_load_result"))->IsUndefined());
18987 CHECK(context->Global()->Get(v8_str("keyed_load_result2"))->IsUndefined());
18988 CHECK(context->Global()->Get(v8_str("y_from_obj"))->IsUndefined());
18989 CHECK(context->Global()->Get(v8_str("y_from_subobj"))->IsUndefined());
18993 THREADED_TEST(Regress142088) {
18994 i::FLAG_allow_natives_syntax = true;
18995 LocalContext context;
18996 v8::Isolate* isolate = context->GetIsolate();
18997 v8::HandleScope scope(isolate);
18998 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
18999 templ->SetAccessor(v8_str("foo"),
19000 GetterWhichReturns42,
19001 SetterWhichSetsYOnThisTo23);
19002 context->Global()->Set(v8_str("obj"), templ->NewInstance());
19004 CompileRun("function load(x) { return x.foo; }"
19005 "var o = Object.create(obj);"
19006 "%OptimizeObjectForAddingMultipleProperties(obj, 1);"
19007 "load(o); load(o); load(o); load(o);");
19011 THREADED_TEST(Regress137496) {
19012 i::FLAG_expose_gc = true;
19013 LocalContext context;
19014 v8::HandleScope scope(context->GetIsolate());
19016 // Compile a try-finally clause where the finally block causes a GC
19017 // while there still is a message pending for external reporting.
19018 TryCatch try_catch(context->GetIsolate());
19019 try_catch.SetVerbose(true);
19020 CompileRun("try { throw new Error(); } finally { gc(); }");
19021 CHECK(try_catch.HasCaught());
19025 THREADED_TEST(Regress157124) {
19026 LocalContext context;
19027 v8::Isolate* isolate = context->GetIsolate();
19028 v8::HandleScope scope(isolate);
19029 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19030 Local<Object> obj = templ->NewInstance();
19031 obj->GetIdentityHash();
19032 obj->DeleteHiddenValue(v8_str("Bug"));
19036 THREADED_TEST(Regress2535) {
19037 LocalContext context;
19038 v8::HandleScope scope(context->GetIsolate());
19039 Local<Value> set_value = CompileRun("new Set();");
19040 Local<Object> set_object(Local<Object>::Cast(set_value));
19041 CHECK_EQ(0, set_object->InternalFieldCount());
19042 Local<Value> map_value = CompileRun("new Map();");
19043 Local<Object> map_object(Local<Object>::Cast(map_value));
19044 CHECK_EQ(0, map_object->InternalFieldCount());
19048 THREADED_TEST(Regress2746) {
19049 LocalContext context;
19050 v8::Isolate* isolate = context->GetIsolate();
19051 v8::HandleScope scope(isolate);
19052 Local<Object> obj = Object::New(isolate);
19053 Local<String> key = String::NewFromUtf8(context->GetIsolate(), "key");
19054 obj->SetHiddenValue(key, v8::Undefined(isolate));
19055 Local<Value> value = obj->GetHiddenValue(key);
19056 CHECK(!value.IsEmpty());
19057 CHECK(value->IsUndefined());
19061 THREADED_TEST(Regress260106) {
19062 LocalContext context;
19063 v8::Isolate* isolate = context->GetIsolate();
19064 v8::HandleScope scope(isolate);
19065 Local<FunctionTemplate> templ = FunctionTemplate::New(isolate,
19067 CompileRun("for (var i = 0; i < 128; i++) Object.prototype[i] = 0;");
19068 Local<Function> function = templ->GetFunction();
19069 CHECK(!function.IsEmpty());
19070 CHECK(function->IsFunction());
19074 THREADED_TEST(JSONParseObject) {
19075 LocalContext context;
19076 HandleScope scope(context->GetIsolate());
19077 Local<Value> obj = v8::JSON::Parse(v8_str("{\"x\":42}"));
19078 Handle<Object> global = context->Global();
19079 global->Set(v8_str("obj"), obj);
19080 ExpectString("JSON.stringify(obj)", "{\"x\":42}");
19084 THREADED_TEST(JSONParseNumber) {
19085 LocalContext context;
19086 HandleScope scope(context->GetIsolate());
19087 Local<Value> obj = v8::JSON::Parse(v8_str("42"));
19088 Handle<Object> global = context->Global();
19089 global->Set(v8_str("obj"), obj);
19090 ExpectString("JSON.stringify(obj)", "42");
19094 #if V8_OS_POSIX && !V8_OS_NACL
19095 class ThreadInterruptTest {
19097 ThreadInterruptTest() : sem_(0), sem_value_(0) { }
19098 ~ThreadInterruptTest() {}
19101 InterruptThread i_thread(this);
19105 CHECK_EQ(kExpectedValue, sem_value_);
19109 static const int kExpectedValue = 1;
19111 class InterruptThread : public v8::base::Thread {
19113 explicit InterruptThread(ThreadInterruptTest* test)
19114 : Thread(Options("InterruptThread")), test_(test) {}
19116 virtual void Run() {
19117 struct sigaction action;
19119 // Ensure that we'll enter waiting condition
19120 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
19122 // Setup signal handler
19123 memset(&action, 0, sizeof(action));
19124 action.sa_handler = SignalHandler;
19125 sigaction(SIGCHLD, &action, NULL);
19128 kill(getpid(), SIGCHLD);
19130 // Ensure that if wait has returned because of error
19131 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
19133 // Set value and signal semaphore
19134 test_->sem_value_ = 1;
19135 test_->sem_.Signal();
19138 static void SignalHandler(int signal) {
19142 ThreadInterruptTest* test_;
19145 v8::base::Semaphore sem_;
19146 volatile int sem_value_;
19150 THREADED_TEST(SemaphoreInterruption) {
19151 ThreadInterruptTest().RunTest();
19155 #endif // V8_OS_POSIX
19158 void UnreachableCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19163 TEST(JSONStringifyAccessCheck) {
19164 v8::V8::Initialize();
19165 v8::Isolate* isolate = CcTest::isolate();
19166 v8::HandleScope scope(isolate);
19168 // Create an ObjectTemplate for global objects and install access
19169 // check callbacks that will block access.
19170 v8::Handle<v8::ObjectTemplate> global_template =
19171 v8::ObjectTemplate::New(isolate);
19172 global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
19174 // Create a context and set an x property on it's global object.
19175 LocalContext context0(NULL, global_template);
19176 v8::Handle<v8::Object> global0 = context0->Global();
19177 global0->Set(v8_str("x"), v8_num(42));
19178 ExpectString("JSON.stringify(this)", "{\"x\":42}");
19180 for (int i = 0; i < 2; i++) {
19182 // Install a toJSON function on the second run.
19183 v8::Handle<v8::FunctionTemplate> toJSON =
19184 v8::FunctionTemplate::New(isolate, UnreachableCallback);
19186 global0->Set(v8_str("toJSON"), toJSON->GetFunction());
19188 // Create a context with a different security token so that the
19189 // failed access check callback will be called on each access.
19190 LocalContext context1(NULL, global_template);
19191 context1->Global()->Set(v8_str("other"), global0);
19193 CHECK(CompileRun("JSON.stringify(other)").IsEmpty());
19194 CHECK(CompileRun("JSON.stringify({ 'a' : other, 'b' : ['c'] })").IsEmpty());
19195 CHECK(CompileRun("JSON.stringify([other, 'b', 'c'])").IsEmpty());
19200 bool access_check_fail_thrown = false;
19201 bool catch_callback_called = false;
19204 // Failed access check callback that performs a GC on each invocation.
19205 void FailedAccessCheckThrows(Local<v8::Object> target,
19206 v8::AccessType type,
19207 Local<v8::Value> data) {
19208 access_check_fail_thrown = true;
19209 i::PrintF("Access check failed. Error thrown.\n");
19210 CcTest::isolate()->ThrowException(
19211 v8::Exception::Error(v8_str("cross context")));
19215 void CatcherCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19216 for (int i = 0; i < args.Length(); i++) {
19217 i::PrintF("%s\n", *String::Utf8Value(args[i]));
19219 catch_callback_called = true;
19223 void HasOwnPropertyCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
19224 args[0]->ToObject(args.GetIsolate())->HasOwnProperty(
19225 args[1]->ToString(args.GetIsolate()));
19229 void CheckCorrectThrow(const char* script) {
19230 // Test that the script, when wrapped into a try-catch, triggers the catch
19231 // clause due to failed access check throwing an exception.
19232 // The subsequent try-catch should run without any exception.
19233 access_check_fail_thrown = false;
19234 catch_callback_called = false;
19235 i::ScopedVector<char> source(1024);
19236 i::SNPrintF(source, "try { %s; } catch (e) { catcher(e); }", script);
19237 CompileRun(source.start());
19238 CHECK(access_check_fail_thrown);
19239 CHECK(catch_callback_called);
19241 access_check_fail_thrown = false;
19242 catch_callback_called = false;
19243 CompileRun("try { [1, 2, 3].sort(); } catch (e) { catcher(e) };");
19244 CHECK(!access_check_fail_thrown);
19245 CHECK(!catch_callback_called);
19249 TEST(AccessCheckThrows) {
19250 i::FLAG_allow_natives_syntax = true;
19251 i::FLAG_turbo_try_catch = true;
19252 v8::V8::Initialize();
19253 v8::V8::SetFailedAccessCheckCallbackFunction(&FailedAccessCheckThrows);
19254 v8::Isolate* isolate = CcTest::isolate();
19255 v8::HandleScope scope(isolate);
19257 // Create an ObjectTemplate for global objects and install access
19258 // check callbacks that will block access.
19259 v8::Handle<v8::ObjectTemplate> global_template =
19260 v8::ObjectTemplate::New(isolate);
19261 global_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
19263 // Create a context and set an x property on it's global object.
19264 LocalContext context0(NULL, global_template);
19265 v8::Handle<v8::Object> global0 = context0->Global();
19267 // Create a context with a different security token so that the
19268 // failed access check callback will be called on each access.
19269 LocalContext context1(NULL, global_template);
19270 context1->Global()->Set(v8_str("other"), global0);
19272 v8::Handle<v8::FunctionTemplate> catcher_fun =
19273 v8::FunctionTemplate::New(isolate, CatcherCallback);
19274 context1->Global()->Set(v8_str("catcher"), catcher_fun->GetFunction());
19276 v8::Handle<v8::FunctionTemplate> has_own_property_fun =
19277 v8::FunctionTemplate::New(isolate, HasOwnPropertyCallback);
19278 context1->Global()->Set(v8_str("has_own_property"),
19279 has_own_property_fun->GetFunction());
19282 v8::TryCatch try_catch(isolate);
19283 access_check_fail_thrown = false;
19284 CompileRun("other.x;");
19285 CHECK(access_check_fail_thrown);
19286 CHECK(try_catch.HasCaught());
19289 CheckCorrectThrow("other.x");
19290 CheckCorrectThrow("other[1]");
19291 CheckCorrectThrow("JSON.stringify(other)");
19292 CheckCorrectThrow("has_own_property(other, 'x')");
19293 CheckCorrectThrow("%GetProperty(other, 'x')");
19294 CheckCorrectThrow("%SetProperty(other, 'x', 'foo', 0)");
19295 CheckCorrectThrow("%AddNamedProperty(other, 'x', 'foo', 1)");
19296 CheckCorrectThrow("%DeleteProperty_Sloppy(other, 'x')");
19297 CheckCorrectThrow("%DeleteProperty_Strict(other, 'x')");
19298 CheckCorrectThrow("%DeleteProperty_Sloppy(other, '1')");
19299 CheckCorrectThrow("%DeleteProperty_Strict(other, '1')");
19300 CheckCorrectThrow("%HasOwnProperty(other, 'x')");
19301 CheckCorrectThrow("%HasProperty('x', other)");
19302 CheckCorrectThrow("%IsPropertyEnumerable(other, 'x')");
19303 // PROPERTY_ATTRIBUTES_NONE = 0
19304 CheckCorrectThrow("%DefineAccessorPropertyUnchecked("
19305 "other, 'x', null, null, 1)");
19307 // Reset the failed access check callback so it does not influence
19308 // the other tests.
19309 v8::V8::SetFailedAccessCheckCallbackFunction(NULL);
19313 class RequestInterruptTestBase {
19315 RequestInterruptTestBase()
19317 isolate_(env_->GetIsolate()),
19320 should_continue_(true) {
19323 virtual ~RequestInterruptTestBase() { }
19325 virtual void StartInterruptThread() = 0;
19327 virtual void TestBody() = 0;
19330 StartInterruptThread();
19332 v8::HandleScope handle_scope(isolate_);
19336 // Verify we arrived here because interruptor was called
19337 // not due to a bug causing us to exit the loop too early.
19338 CHECK(!should_continue());
19341 void WakeUpInterruptor() {
19345 bool should_continue() const { return should_continue_; }
19347 bool ShouldContinue() {
19349 if (--warmup_ == 0) {
19350 WakeUpInterruptor();
19354 return should_continue_;
19357 static void ShouldContinueCallback(
19358 const v8::FunctionCallbackInfo<Value>& info) {
19359 RequestInterruptTestBase* test =
19360 reinterpret_cast<RequestInterruptTestBase*>(
19361 info.Data().As<v8::External>()->Value());
19362 info.GetReturnValue().Set(test->ShouldContinue());
19366 v8::Isolate* isolate_;
19367 v8::base::Semaphore sem_;
19369 bool should_continue_;
19373 class RequestInterruptTestBaseWithSimpleInterrupt
19374 : public RequestInterruptTestBase {
19376 RequestInterruptTestBaseWithSimpleInterrupt() : i_thread(this) { }
19378 virtual void StartInterruptThread() {
19383 class InterruptThread : public v8::base::Thread {
19385 explicit InterruptThread(RequestInterruptTestBase* test)
19386 : Thread(Options("RequestInterruptTest")), test_(test) {}
19388 virtual void Run() {
19389 test_->sem_.Wait();
19390 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
19393 static void OnInterrupt(v8::Isolate* isolate, void* data) {
19394 reinterpret_cast<RequestInterruptTestBase*>(data)->
19395 should_continue_ = false;
19399 RequestInterruptTestBase* test_;
19402 InterruptThread i_thread;
19406 class RequestInterruptTestWithFunctionCall
19407 : public RequestInterruptTestBaseWithSimpleInterrupt {
19409 virtual void TestBody() {
19410 Local<Function> func = Function::New(
19411 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
19412 env_->Global()->Set(v8_str("ShouldContinue"), func);
19414 CompileRun("while (ShouldContinue()) { }");
19419 class RequestInterruptTestWithMethodCall
19420 : public RequestInterruptTestBaseWithSimpleInterrupt {
19422 virtual void TestBody() {
19423 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19424 v8::Local<v8::Template> proto = t->PrototypeTemplate();
19425 proto->Set(v8_str("shouldContinue"), Function::New(
19426 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19427 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19429 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
19434 class RequestInterruptTestWithAccessor
19435 : public RequestInterruptTestBaseWithSimpleInterrupt {
19437 virtual void TestBody() {
19438 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19439 v8::Local<v8::Template> proto = t->PrototypeTemplate();
19440 proto->SetAccessorProperty(v8_str("shouldContinue"), FunctionTemplate::New(
19441 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19442 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19444 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
19449 class RequestInterruptTestWithNativeAccessor
19450 : public RequestInterruptTestBaseWithSimpleInterrupt {
19452 virtual void TestBody() {
19453 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19454 t->InstanceTemplate()->SetNativeDataProperty(
19455 v8_str("shouldContinue"),
19456 &ShouldContinueNativeGetter,
19458 v8::External::New(isolate_, this));
19459 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19461 CompileRun("var obj = new Klass; while (obj.shouldContinue) { }");
19465 static void ShouldContinueNativeGetter(
19466 Local<String> property,
19467 const v8::PropertyCallbackInfo<v8::Value>& info) {
19468 RequestInterruptTestBase* test =
19469 reinterpret_cast<RequestInterruptTestBase*>(
19470 info.Data().As<v8::External>()->Value());
19471 info.GetReturnValue().Set(test->ShouldContinue());
19476 class RequestInterruptTestWithMethodCallAndInterceptor
19477 : public RequestInterruptTestBaseWithSimpleInterrupt {
19479 virtual void TestBody() {
19480 v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(isolate_);
19481 v8::Local<v8::Template> proto = t->PrototypeTemplate();
19482 proto->Set(v8_str("shouldContinue"), Function::New(
19483 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this)));
19484 v8::Local<v8::ObjectTemplate> instance_template = t->InstanceTemplate();
19485 instance_template->SetHandler(
19486 v8::NamedPropertyHandlerConfiguration(EmptyInterceptor));
19488 env_->Global()->Set(v8_str("Klass"), t->GetFunction());
19490 CompileRun("var obj = new Klass; while (obj.shouldContinue()) { }");
19494 static void EmptyInterceptor(
19495 Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) {}
19499 class RequestInterruptTestWithMathAbs
19500 : public RequestInterruptTestBaseWithSimpleInterrupt {
19502 virtual void TestBody() {
19503 env_->Global()->Set(v8_str("WakeUpInterruptor"), Function::New(
19505 WakeUpInterruptorCallback,
19506 v8::External::New(isolate_, this)));
19508 env_->Global()->Set(v8_str("ShouldContinue"), Function::New(
19510 ShouldContinueCallback,
19511 v8::External::New(isolate_, this)));
19513 i::FLAG_allow_natives_syntax = true;
19514 CompileRun("function loopish(o) {"
19516 " while (o.abs(1) > 0) {"
19517 " if (o.abs(1) >= 0 && !ShouldContinue()) break;"
19519 " if (--pre === 0) WakeUpInterruptor(o === Math);"
19524 "var obj = {abs: function () { return i-- }, x: null};"
19527 "%OptimizeFunctionOnNextCall(loopish);"
19530 i::FLAG_allow_natives_syntax = false;
19534 static void WakeUpInterruptorCallback(
19535 const v8::FunctionCallbackInfo<Value>& info) {
19536 if (!info[0]->BooleanValue()) return;
19538 RequestInterruptTestBase* test =
19539 reinterpret_cast<RequestInterruptTestBase*>(
19540 info.Data().As<v8::External>()->Value());
19541 test->WakeUpInterruptor();
19544 static void ShouldContinueCallback(
19545 const v8::FunctionCallbackInfo<Value>& info) {
19546 RequestInterruptTestBase* test =
19547 reinterpret_cast<RequestInterruptTestBase*>(
19548 info.Data().As<v8::External>()->Value());
19549 info.GetReturnValue().Set(test->should_continue());
19554 TEST(RequestInterruptTestWithFunctionCall) {
19555 RequestInterruptTestWithFunctionCall().RunTest();
19559 TEST(RequestInterruptTestWithMethodCall) {
19560 RequestInterruptTestWithMethodCall().RunTest();
19564 TEST(RequestInterruptTestWithAccessor) {
19565 RequestInterruptTestWithAccessor().RunTest();
19569 TEST(RequestInterruptTestWithNativeAccessor) {
19570 RequestInterruptTestWithNativeAccessor().RunTest();
19574 TEST(RequestInterruptTestWithMethodCallAndInterceptor) {
19575 RequestInterruptTestWithMethodCallAndInterceptor().RunTest();
19579 TEST(RequestInterruptTestWithMathAbs) {
19580 RequestInterruptTestWithMathAbs().RunTest();
19584 class RequestMultipleInterrupts : public RequestInterruptTestBase {
19586 RequestMultipleInterrupts() : i_thread(this), counter_(0) {}
19588 virtual void StartInterruptThread() {
19592 virtual void TestBody() {
19593 Local<Function> func = Function::New(
19594 isolate_, ShouldContinueCallback, v8::External::New(isolate_, this));
19595 env_->Global()->Set(v8_str("ShouldContinue"), func);
19597 CompileRun("while (ShouldContinue()) { }");
19601 class InterruptThread : public v8::base::Thread {
19603 enum { NUM_INTERRUPTS = 10 };
19604 explicit InterruptThread(RequestMultipleInterrupts* test)
19605 : Thread(Options("RequestInterruptTest")), test_(test) {}
19607 virtual void Run() {
19608 test_->sem_.Wait();
19609 for (int i = 0; i < NUM_INTERRUPTS; i++) {
19610 test_->isolate_->RequestInterrupt(&OnInterrupt, test_);
19614 static void OnInterrupt(v8::Isolate* isolate, void* data) {
19615 RequestMultipleInterrupts* test =
19616 reinterpret_cast<RequestMultipleInterrupts*>(data);
19617 test->should_continue_ = ++test->counter_ < NUM_INTERRUPTS;
19621 RequestMultipleInterrupts* test_;
19624 InterruptThread i_thread;
19629 TEST(RequestMultipleInterrupts) { RequestMultipleInterrupts().RunTest(); }
19632 static bool interrupt_was_called = false;
19635 void SmallScriptsInterruptCallback(v8::Isolate* isolate, void* data) {
19636 interrupt_was_called = true;
19640 TEST(RequestInterruptSmallScripts) {
19642 v8::Isolate* isolate = CcTest::isolate();
19643 v8::HandleScope scope(isolate);
19645 interrupt_was_called = false;
19646 isolate->RequestInterrupt(&SmallScriptsInterruptCallback, NULL);
19647 CompileRun("(function(x){return x;})(1);");
19648 CHECK(interrupt_was_called);
19652 static Local<Value> function_new_expected_env;
19653 static void FunctionNewCallback(const v8::FunctionCallbackInfo<Value>& info) {
19654 CHECK(function_new_expected_env->Equals(info.Data()));
19655 info.GetReturnValue().Set(17);
19659 THREADED_TEST(FunctionNew) {
19661 v8::Isolate* isolate = env->GetIsolate();
19662 v8::HandleScope scope(isolate);
19663 Local<Object> data = v8::Object::New(isolate);
19664 function_new_expected_env = data;
19665 Local<Function> func = Function::New(isolate, FunctionNewCallback, data);
19666 env->Global()->Set(v8_str("func"), func);
19667 Local<Value> result = CompileRun("func();");
19668 CHECK(v8::Integer::New(isolate, 17)->Equals(result));
19669 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
19670 // Verify function not cached
19671 auto serial_number = handle(i::Smi::cast(v8::Utils::OpenHandle(*func)
19673 ->get_api_func_data()
19674 ->serial_number()),
19676 auto cache = i_isolate->function_cache();
19677 CHECK(cache->Lookup(serial_number)->IsTheHole());
19678 // Verify that each Function::New creates a new function instance
19679 Local<Object> data2 = v8::Object::New(isolate);
19680 function_new_expected_env = data2;
19681 Local<Function> func2 = Function::New(isolate, FunctionNewCallback, data2);
19682 CHECK(!func2->IsNull());
19683 CHECK(!func->Equals(func2));
19684 env->Global()->Set(v8_str("func2"), func2);
19685 Local<Value> result2 = CompileRun("func2();");
19686 CHECK(v8::Integer::New(isolate, 17)->Equals(result2));
19690 TEST(EscapeableHandleScope) {
19691 HandleScope outer_scope(CcTest::isolate());
19692 LocalContext context;
19693 const int runs = 10;
19694 Local<String> values[runs];
19695 for (int i = 0; i < runs; i++) {
19696 v8::EscapableHandleScope inner_scope(CcTest::isolate());
19697 Local<String> value;
19698 if (i != 0) value = v8_str("escape value");
19699 values[i] = inner_scope.Escape(value);
19701 for (int i = 0; i < runs; i++) {
19702 Local<String> expected;
19704 CHECK(v8_str("escape value")->Equals(values[i]));
19706 CHECK(values[i].IsEmpty());
19712 static void SetterWhichExpectsThisAndHolderToDiffer(
19713 Local<String>, Local<Value>, const v8::PropertyCallbackInfo<void>& info) {
19714 CHECK(info.Holder() != info.This());
19718 TEST(Regress239669) {
19719 LocalContext context;
19720 v8::Isolate* isolate = context->GetIsolate();
19721 v8::HandleScope scope(isolate);
19722 Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
19723 templ->SetAccessor(v8_str("x"), 0, SetterWhichExpectsThisAndHolderToDiffer);
19724 context->Global()->Set(v8_str("P"), templ->NewInstance());
19729 "C1.prototype = P;"
19730 "for (var i = 0; i < 4; i++ ) {"
19736 class ApiCallOptimizationChecker {
19738 static Local<Object> data;
19739 static Local<Object> receiver;
19740 static Local<Object> holder;
19741 static Local<Object> callee;
19744 static void OptimizationCallback(
19745 const v8::FunctionCallbackInfo<v8::Value>& info) {
19746 CHECK(callee == info.Callee());
19747 CHECK(data == info.Data());
19748 CHECK(receiver == info.This());
19749 if (info.Length() == 1) {
19750 CHECK(v8_num(1)->Equals(info[0]));
19752 CHECK(holder == info.Holder());
19754 info.GetReturnValue().Set(v8_str("returned"));
19758 enum SignatureType {
19760 kSignatureOnReceiver,
19761 kSignatureOnPrototype
19765 SignatureType signature_types[] =
19766 {kNoSignature, kSignatureOnReceiver, kSignatureOnPrototype};
19767 for (unsigned i = 0; i < arraysize(signature_types); i++) {
19768 SignatureType signature_type = signature_types[i];
19769 for (int j = 0; j < 2; j++) {
19770 bool global = j == 0;
19771 int key = signature_type +
19772 arraysize(signature_types) * (global ? 1 : 0);
19773 Run(signature_type, global, key);
19778 void Run(SignatureType signature_type, bool global, int key) {
19779 v8::Isolate* isolate = CcTest::isolate();
19780 v8::HandleScope scope(isolate);
19781 // Build a template for signature checks.
19782 Local<v8::ObjectTemplate> signature_template;
19783 Local<v8::Signature> signature;
19785 Local<v8::FunctionTemplate> parent_template =
19786 FunctionTemplate::New(isolate);
19787 parent_template->SetHiddenPrototype(true);
19788 Local<v8::FunctionTemplate> function_template
19789 = FunctionTemplate::New(isolate);
19790 function_template->Inherit(parent_template);
19791 switch (signature_type) {
19794 case kSignatureOnReceiver:
19795 signature = v8::Signature::New(isolate, function_template);
19797 case kSignatureOnPrototype:
19798 signature = v8::Signature::New(isolate, parent_template);
19801 signature_template = function_template->InstanceTemplate();
19803 // Global object must pass checks.
19804 Local<v8::Context> context =
19805 v8::Context::New(isolate, NULL, signature_template);
19806 v8::Context::Scope context_scope(context);
19807 // Install regular object that can pass signature checks.
19808 Local<Object> function_receiver = signature_template->NewInstance();
19809 context->Global()->Set(v8_str("function_receiver"), function_receiver);
19810 // Get the holder objects.
19811 Local<Object> inner_global =
19812 Local<Object>::Cast(context->Global()->GetPrototype());
19813 // Install functions on hidden prototype object if there is one.
19814 data = Object::New(isolate);
19815 Local<FunctionTemplate> function_template = FunctionTemplate::New(
19816 isolate, OptimizationCallback, data, signature);
19817 Local<Function> function = function_template->GetFunction();
19818 Local<Object> global_holder = inner_global;
19819 Local<Object> function_holder = function_receiver;
19820 if (signature_type == kSignatureOnPrototype) {
19821 function_holder = Local<Object>::Cast(function_holder->GetPrototype());
19822 global_holder = Local<Object>::Cast(global_holder->GetPrototype());
19824 global_holder->Set(v8_str("g_f"), function);
19825 global_holder->SetAccessorProperty(v8_str("g_acc"), function, function);
19826 function_holder->Set(v8_str("f"), function);
19827 function_holder->SetAccessorProperty(v8_str("acc"), function, function);
19828 // Initialize expected values.
19832 receiver = context->Global();
19833 holder = inner_global;
19835 holder = function_receiver;
19836 // If not using a signature, add something else to the prototype chain
19837 // to test the case that holder != receiver
19838 if (signature_type == kNoSignature) {
19839 receiver = Local<Object>::Cast(CompileRun(
19840 "var receiver_subclass = {};\n"
19841 "receiver_subclass.__proto__ = function_receiver;\n"
19842 "receiver_subclass"));
19844 receiver = Local<Object>::Cast(CompileRun(
19845 "var receiver_subclass = function_receiver;\n"
19846 "receiver_subclass"));
19849 // With no signature, the holder is not set.
19850 if (signature_type == kNoSignature) holder = receiver;
19851 // build wrap_function
19852 i::ScopedVector<char> wrap_function(200);
19856 "function wrap_f_%d() { var f = g_f; return f(); }\n"
19857 "function wrap_get_%d() { return this.g_acc; }\n"
19858 "function wrap_set_%d() { return this.g_acc = 1; }\n",
19863 "function wrap_f_%d() { return receiver_subclass.f(); }\n"
19864 "function wrap_get_%d() { return receiver_subclass.acc; }\n"
19865 "function wrap_set_%d() { return receiver_subclass.acc = 1; }\n",
19868 // build source string
19869 i::ScopedVector<char> source(1000);
19872 "%s\n" // wrap functions
19873 "function wrap_f() { return wrap_f_%d(); }\n"
19874 "function wrap_get() { return wrap_get_%d(); }\n"
19875 "function wrap_set() { return wrap_set_%d(); }\n"
19876 "check = function(returned) {\n"
19877 " if (returned !== 'returned') { throw returned; }\n"
19880 "check(wrap_f());\n"
19881 "check(wrap_f());\n"
19882 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n"
19883 "check(wrap_f());\n"
19885 "check(wrap_get());\n"
19886 "check(wrap_get());\n"
19887 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n"
19888 "check(wrap_get());\n"
19890 "check = function(returned) {\n"
19891 " if (returned !== 1) { throw returned; }\n"
19893 "check(wrap_set());\n"
19894 "check(wrap_set());\n"
19895 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n"
19896 "check(wrap_set());\n",
19897 wrap_function.start(), key, key, key, key, key, key);
19898 v8::TryCatch try_catch(isolate);
19899 CompileRun(source.start());
19900 DCHECK(!try_catch.HasCaught());
19901 CHECK_EQ(9, count);
19906 Local<Object> ApiCallOptimizationChecker::data;
19907 Local<Object> ApiCallOptimizationChecker::receiver;
19908 Local<Object> ApiCallOptimizationChecker::holder;
19909 Local<Object> ApiCallOptimizationChecker::callee;
19910 int ApiCallOptimizationChecker::count = 0;
19913 TEST(FunctionCallOptimization) {
19914 i::FLAG_allow_natives_syntax = true;
19915 ApiCallOptimizationChecker checker;
19920 TEST(FunctionCallOptimizationMultipleArgs) {
19921 i::FLAG_allow_natives_syntax = true;
19922 LocalContext context;
19923 v8::Isolate* isolate = context->GetIsolate();
19924 v8::HandleScope scope(isolate);
19925 Handle<Object> global = context->Global();
19926 Local<v8::Function> function = Function::New(isolate, Returns42);
19927 global->Set(v8_str("x"), function);
19929 "function x_wrap() {\n"
19930 " for (var i = 0; i < 5; i++) {\n"
19935 "%OptimizeFunctionOnNextCall(x_wrap);"
19940 static void ReturnsSymbolCallback(
19941 const v8::FunctionCallbackInfo<v8::Value>& info) {
19942 info.GetReturnValue().Set(v8::Symbol::New(info.GetIsolate()));
19946 TEST(ApiCallbackCanReturnSymbols) {
19947 i::FLAG_allow_natives_syntax = true;
19948 LocalContext context;
19949 v8::Isolate* isolate = context->GetIsolate();
19950 v8::HandleScope scope(isolate);
19951 Handle<Object> global = context->Global();
19952 Local<v8::Function> function = Function::New(isolate, ReturnsSymbolCallback);
19953 global->Set(v8_str("x"), function);
19955 "function x_wrap() {\n"
19956 " for (var i = 0; i < 5; i++) {\n"
19961 "%OptimizeFunctionOnNextCall(x_wrap);"
19966 TEST(EmptyApiCallback) {
19967 LocalContext context;
19968 auto isolate = context->GetIsolate();
19969 v8::HandleScope scope(isolate);
19970 auto global = context->Global();
19971 auto function = FunctionTemplate::New(isolate)->GetFunction();
19972 global->Set(v8_str("x"), function);
19974 auto result = CompileRun("x()");
19975 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
19977 result = CompileRun("x(1,2,3)");
19978 CHECK(v8::Utils::OpenHandle(*result)->IsJSGlobalProxy());
19980 result = CompileRun("7 + x.call(3) + 11");
19981 CHECK(result->IsInt32());
19982 CHECK_EQ(21, result->Int32Value());
19984 result = CompileRun("7 + x.call(3, 101, 102, 103, 104) + 11");
19985 CHECK(result->IsInt32());
19986 CHECK_EQ(21, result->Int32Value());
19988 result = CompileRun("var y = []; x.call(y)");
19989 CHECK(result->IsArray());
19991 result = CompileRun("x.call(y, 1, 2, 3, 4)");
19992 CHECK(result->IsArray());
19996 TEST(SimpleSignatureCheck) {
19997 LocalContext context;
19998 auto isolate = context->GetIsolate();
19999 v8::HandleScope scope(isolate);
20000 auto global = context->Global();
20001 auto sig_obj = FunctionTemplate::New(isolate);
20002 auto sig = v8::Signature::New(isolate, sig_obj);
20003 auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20004 global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20005 global->Set(v8_str("x"), x->GetFunction());
20006 CompileRun("var s = new sig_obj();");
20008 TryCatch try_catch(isolate);
20010 CHECK(try_catch.HasCaught());
20013 TryCatch try_catch(isolate);
20014 CompileRun("x.call(1)");
20015 CHECK(try_catch.HasCaught());
20018 TryCatch try_catch(isolate);
20019 auto result = CompileRun("s.x = x; s.x()");
20020 CHECK(!try_catch.HasCaught());
20021 CHECK_EQ(42, result->Int32Value());
20024 TryCatch try_catch(isolate);
20025 auto result = CompileRun("x.call(s)");
20026 CHECK(!try_catch.HasCaught());
20027 CHECK_EQ(42, result->Int32Value());
20032 TEST(ChainSignatureCheck) {
20033 LocalContext context;
20034 auto isolate = context->GetIsolate();
20035 v8::HandleScope scope(isolate);
20036 auto global = context->Global();
20037 auto sig_obj = FunctionTemplate::New(isolate);
20038 auto sig = v8::Signature::New(isolate, sig_obj);
20039 for (int i = 0; i < 4; ++i) {
20040 auto temp = FunctionTemplate::New(isolate);
20041 temp->Inherit(sig_obj);
20044 auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20045 global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20046 global->Set(v8_str("x"), x->GetFunction());
20047 CompileRun("var s = new sig_obj();");
20049 TryCatch try_catch(isolate);
20051 CHECK(try_catch.HasCaught());
20054 TryCatch try_catch(isolate);
20055 CompileRun("x.call(1)");
20056 CHECK(try_catch.HasCaught());
20059 TryCatch try_catch(isolate);
20060 auto result = CompileRun("s.x = x; s.x()");
20061 CHECK(!try_catch.HasCaught());
20062 CHECK_EQ(42, result->Int32Value());
20065 TryCatch try_catch(isolate);
20066 auto result = CompileRun("x.call(s)");
20067 CHECK(!try_catch.HasCaught());
20068 CHECK_EQ(42, result->Int32Value());
20073 TEST(PrototypeSignatureCheck) {
20074 LocalContext context;
20075 auto isolate = context->GetIsolate();
20076 v8::HandleScope scope(isolate);
20077 auto global = context->Global();
20078 auto sig_obj = FunctionTemplate::New(isolate);
20079 sig_obj->SetHiddenPrototype(true);
20080 auto sig = v8::Signature::New(isolate, sig_obj);
20081 auto x = FunctionTemplate::New(isolate, Returns42, Handle<Value>(), sig);
20082 global->Set(v8_str("sig_obj"), sig_obj->GetFunction());
20083 global->Set(v8_str("x"), x->GetFunction());
20084 CompileRun("s = {}; s.__proto__ = new sig_obj();");
20086 TryCatch try_catch(isolate);
20088 CHECK(try_catch.HasCaught());
20091 TryCatch try_catch(isolate);
20092 CompileRun("x.call(1)");
20093 CHECK(try_catch.HasCaught());
20096 TryCatch try_catch(isolate);
20097 auto result = CompileRun("s.x = x; s.x()");
20098 CHECK(!try_catch.HasCaught());
20099 CHECK_EQ(42, result->Int32Value());
20102 TryCatch try_catch(isolate);
20103 auto result = CompileRun("x.call(s)");
20104 CHECK(!try_catch.HasCaught());
20105 CHECK_EQ(42, result->Int32Value());
20110 static const char* last_event_message;
20111 static int last_event_status;
20112 void StoringEventLoggerCallback(const char* message, int status) {
20113 last_event_message = message;
20114 last_event_status = status;
20118 TEST(EventLogging) {
20119 v8::Isolate* isolate = CcTest::isolate();
20120 isolate->SetEventLogger(StoringEventLoggerCallback);
20121 v8::internal::HistogramTimer histogramTimer(
20122 "V8.Test", 0, 10000, v8::internal::HistogramTimer::MILLISECOND, 50,
20123 reinterpret_cast<v8::internal::Isolate*>(isolate));
20124 histogramTimer.Start();
20125 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20126 CHECK_EQ(0, last_event_status);
20127 histogramTimer.Stop();
20128 CHECK_EQ(0, strcmp("V8.Test", last_event_message));
20129 CHECK_EQ(1, last_event_status);
20134 LocalContext context;
20135 v8::Isolate* isolate = context->GetIsolate();
20136 v8::HandleScope scope(isolate);
20137 Handle<Object> global = context->Global();
20140 Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20141 Handle<v8::Promise::Resolver> rr = v8::Promise::Resolver::New(isolate);
20142 Handle<v8::Promise> p = pr->GetPromise();
20143 Handle<v8::Promise> r = rr->GetPromise();
20144 CHECK_EQ(isolate, p->GetIsolate());
20146 // IsPromise predicate.
20147 CHECK(p->IsPromise());
20148 CHECK(r->IsPromise());
20149 Handle<Value> o = v8::Object::New(isolate);
20150 CHECK(!o->IsPromise());
20152 // Resolution and rejection.
20153 pr->Resolve(v8::Integer::New(isolate, 1));
20154 CHECK(p->IsPromise());
20155 rr->Reject(v8::Integer::New(isolate, 2));
20156 CHECK(r->IsPromise());
20158 // Chaining non-pending promises.
20162 "function f1(x) { x1 = x; return x+1 };\n"
20163 "function f2(x) { x2 = x; return x+1 };\n");
20164 Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20165 Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20168 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20169 isolate->RunMicrotasks();
20170 CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20173 isolate->RunMicrotasks();
20174 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20177 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20178 isolate->RunMicrotasks();
20179 CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20182 isolate->RunMicrotasks();
20183 CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20185 // Chaining pending promises.
20186 CompileRun("x1 = x2 = 0;");
20187 pr = v8::Promise::Resolver::New(isolate);
20188 rr = v8::Promise::Resolver::New(isolate);
20190 pr->GetPromise()->Chain(f1);
20191 rr->GetPromise()->Catch(f2);
20192 isolate->RunMicrotasks();
20193 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20194 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20196 pr->Resolve(v8::Integer::New(isolate, 1));
20197 rr->Reject(v8::Integer::New(isolate, 2));
20198 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20199 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20201 isolate->RunMicrotasks();
20202 CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20203 CHECK_EQ(2, global->Get(v8_str("x2"))->Int32Value());
20206 CompileRun("x1 = x2 = 0;");
20207 pr = v8::Promise::Resolver::New(isolate);
20208 pr->GetPromise()->Chain(f1)->Chain(f2);
20209 pr->Resolve(v8::Integer::New(isolate, 3));
20210 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20211 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20212 isolate->RunMicrotasks();
20213 CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20214 CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20216 CompileRun("x1 = x2 = 0;");
20217 rr = v8::Promise::Resolver::New(isolate);
20218 rr->GetPromise()->Catch(f1)->Chain(f2);
20219 rr->Reject(v8::Integer::New(isolate, 3));
20220 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20221 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20222 isolate->RunMicrotasks();
20223 CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20224 CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20228 TEST(PromiseThen) {
20229 LocalContext context;
20230 v8::Isolate* isolate = context->GetIsolate();
20231 v8::HandleScope scope(isolate);
20232 Handle<Object> global = context->Global();
20235 Handle<v8::Promise::Resolver> pr = v8::Promise::Resolver::New(isolate);
20236 Handle<v8::Promise::Resolver> qr = v8::Promise::Resolver::New(isolate);
20237 Handle<v8::Promise> p = pr->GetPromise();
20238 Handle<v8::Promise> q = qr->GetPromise();
20240 CHECK(p->IsPromise());
20241 CHECK(q->IsPromise());
20243 pr->Resolve(v8::Integer::New(isolate, 1));
20246 // Chaining non-pending promises.
20250 "function f1(x) { x1 = x; return x+1 };\n"
20251 "function f2(x) { x2 = x; return x+1 };\n");
20252 Handle<Function> f1 = Handle<Function>::Cast(global->Get(v8_str("f1")));
20253 Handle<Function> f2 = Handle<Function>::Cast(global->Get(v8_str("f2")));
20257 CHECK(global->Get(v8_str("x1"))->IsNumber());
20258 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20259 isolate->RunMicrotasks();
20260 CHECK(!global->Get(v8_str("x1"))->IsNumber());
20261 CHECK(p->Equals(global->Get(v8_str("x1"))));
20264 CompileRun("x1 = x2 = 0;");
20266 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20267 isolate->RunMicrotasks();
20268 CHECK_EQ(1, global->Get(v8_str("x1"))->Int32Value());
20271 CompileRun("x1 = x2 = 0;");
20272 pr = v8::Promise::Resolver::New(isolate);
20273 qr = v8::Promise::Resolver::New(isolate);
20276 qr->GetPromise()->Then(f1)->Then(f2);
20278 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20279 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20280 isolate->RunMicrotasks();
20281 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20282 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20284 pr->Resolve(v8::Integer::New(isolate, 3));
20286 CHECK_EQ(0, global->Get(v8_str("x1"))->Int32Value());
20287 CHECK_EQ(0, global->Get(v8_str("x2"))->Int32Value());
20288 isolate->RunMicrotasks();
20289 CHECK_EQ(3, global->Get(v8_str("x1"))->Int32Value());
20290 CHECK_EQ(4, global->Get(v8_str("x2"))->Int32Value());
20294 TEST(DisallowJavascriptExecutionScope) {
20295 LocalContext context;
20296 v8::Isolate* isolate = context->GetIsolate();
20297 v8::HandleScope scope(isolate);
20298 v8::Isolate::DisallowJavascriptExecutionScope no_js(
20299 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20304 TEST(AllowJavascriptExecutionScope) {
20305 LocalContext context;
20306 v8::Isolate* isolate = context->GetIsolate();
20307 v8::HandleScope scope(isolate);
20308 v8::Isolate::DisallowJavascriptExecutionScope no_js(
20309 isolate, v8::Isolate::DisallowJavascriptExecutionScope::CRASH_ON_FAILURE);
20310 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20311 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20312 { v8::Isolate::AllowJavascriptExecutionScope yes_js(isolate);
20318 TEST(ThrowOnJavascriptExecution) {
20319 LocalContext context;
20320 v8::Isolate* isolate = context->GetIsolate();
20321 v8::HandleScope scope(isolate);
20322 v8::TryCatch try_catch(isolate);
20323 v8::Isolate::DisallowJavascriptExecutionScope throw_js(
20324 isolate, v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
20326 CHECK(try_catch.HasCaught());
20330 TEST(Regress354123) {
20331 LocalContext current;
20332 v8::Isolate* isolate = current->GetIsolate();
20333 v8::HandleScope scope(isolate);
20335 v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
20336 templ->SetAccessCheckCallbacks(AccessCounter, NULL);
20337 current->Global()->Set(v8_str("friend"), templ->NewInstance());
20339 // Test access using __proto__ from the prototype chain.
20341 CompileRun("friend.__proto__ = {};");
20342 CHECK_EQ(2, access_count);
20343 CompileRun("friend.__proto__;");
20344 CHECK_EQ(4, access_count);
20346 // Test access using __proto__ as a hijacked function (A).
20348 CompileRun("var p = Object.prototype;"
20349 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').set;"
20350 "f.call(friend, {});");
20351 CHECK_EQ(1, access_count);
20352 CompileRun("var p = Object.prototype;"
20353 "var f = Object.getOwnPropertyDescriptor(p, '__proto__').get;"
20354 "f.call(friend);");
20355 CHECK_EQ(2, access_count);
20357 // Test access using __proto__ as a hijacked function (B).
20359 CompileRun("var f = Object.prototype.__lookupSetter__('__proto__');"
20360 "f.call(friend, {});");
20361 CHECK_EQ(1, access_count);
20362 CompileRun("var f = Object.prototype.__lookupGetter__('__proto__');"
20363 "f.call(friend);");
20364 CHECK_EQ(2, access_count);
20366 // Test access using Object.setPrototypeOf reflective method.
20368 CompileRun("Object.setPrototypeOf(friend, {});");
20369 CHECK_EQ(1, access_count);
20370 CompileRun("Object.getPrototypeOf(friend);");
20371 CHECK_EQ(2, access_count);
20375 TEST(CaptureStackTraceForStackOverflow) {
20376 v8::internal::FLAG_stack_size = 150;
20377 LocalContext current;
20378 v8::Isolate* isolate = current->GetIsolate();
20379 v8::HandleScope scope(isolate);
20380 V8::SetCaptureStackTraceForUncaughtExceptions(
20381 true, 10, v8::StackTrace::kDetailed);
20382 v8::TryCatch try_catch(isolate);
20383 CompileRun("(function f(x) { f(x+1); })(0)");
20384 CHECK(try_catch.HasCaught());
20388 TEST(ScriptNameAndLineNumber) {
20390 v8::Isolate* isolate = env->GetIsolate();
20391 v8::HandleScope scope(isolate);
20392 const char* url = "http://www.foo.com/foo.js";
20393 v8::ScriptOrigin origin(v8_str(url), v8::Integer::New(isolate, 13));
20394 v8::ScriptCompiler::Source script_source(v8_str("var foo;"), origin);
20395 Local<Script> script = v8::ScriptCompiler::Compile(
20396 isolate, &script_source);
20397 Local<Value> script_name = script->GetUnboundScript()->GetScriptName();
20398 CHECK(!script_name.IsEmpty());
20399 CHECK(script_name->IsString());
20400 String::Utf8Value utf8_name(script_name);
20401 CHECK_EQ(0, strcmp(url, *utf8_name));
20402 int line_number = script->GetUnboundScript()->GetLineNumber(0);
20403 CHECK_EQ(13, line_number);
20406 void CheckMagicComments(Handle<Script> script, const char* expected_source_url,
20407 const char* expected_source_mapping_url) {
20408 if (expected_source_url != NULL) {
20409 v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
20410 CHECK_EQ(0, strcmp(expected_source_url, *url));
20412 CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
20414 if (expected_source_mapping_url != NULL) {
20415 v8::String::Utf8Value url(
20416 script->GetUnboundScript()->GetSourceMappingURL());
20417 CHECK_EQ(0, strcmp(expected_source_mapping_url, *url));
20419 CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
20423 void SourceURLHelper(const char* source, const char* expected_source_url,
20424 const char* expected_source_mapping_url) {
20425 Local<Script> script = v8_compile(source);
20426 CheckMagicComments(script, expected_source_url, expected_source_mapping_url);
20430 TEST(ScriptSourceURLAndSourceMappingURL) {
20432 v8::Isolate* isolate = env->GetIsolate();
20433 v8::HandleScope scope(isolate);
20434 SourceURLHelper("function foo() {}\n"
20435 "//# sourceURL=bar1.js\n", "bar1.js", NULL);
20436 SourceURLHelper("function foo() {}\n"
20437 "//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
20439 // Both sourceURL and sourceMappingURL.
20440 SourceURLHelper("function foo() {}\n"
20441 "//# sourceURL=bar3.js\n"
20442 "//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
20444 // Two source URLs; the first one is ignored.
20445 SourceURLHelper("function foo() {}\n"
20446 "//# sourceURL=ignoreme.js\n"
20447 "//# sourceURL=bar5.js\n", "bar5.js", NULL);
20448 SourceURLHelper("function foo() {}\n"
20449 "//# sourceMappingURL=ignoreme.js\n"
20450 "//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
20452 // SourceURL or sourceMappingURL in the middle of the script.
20453 SourceURLHelper("function foo() {}\n"
20454 "//# sourceURL=bar7.js\n"
20455 "function baz() {}\n", "bar7.js", NULL);
20456 SourceURLHelper("function foo() {}\n"
20457 "//# sourceMappingURL=bar8.js\n"
20458 "function baz() {}\n", NULL, "bar8.js");
20460 // Too much whitespace.
20461 SourceURLHelper("function foo() {}\n"
20462 "//# sourceURL=bar9.js\n"
20463 "//# sourceMappingURL=bar10.js\n", NULL, NULL);
20464 SourceURLHelper("function foo() {}\n"
20465 "//# sourceURL =bar11.js\n"
20466 "//# sourceMappingURL =bar12.js\n", NULL, NULL);
20468 // Disallowed characters in value.
20469 SourceURLHelper("function foo() {}\n"
20470 "//# sourceURL=bar13 .js \n"
20471 "//# sourceMappingURL=bar14 .js \n",
20473 SourceURLHelper("function foo() {}\n"
20474 "//# sourceURL=bar15\t.js \n"
20475 "//# sourceMappingURL=bar16\t.js \n",
20477 SourceURLHelper("function foo() {}\n"
20478 "//# sourceURL=bar17'.js \n"
20479 "//# sourceMappingURL=bar18'.js \n",
20481 SourceURLHelper("function foo() {}\n"
20482 "//# sourceURL=bar19\".js \n"
20483 "//# sourceMappingURL=bar20\".js \n",
20486 // Not too much whitespace.
20487 SourceURLHelper("function foo() {}\n"
20488 "//# sourceURL= bar21.js \n"
20489 "//# sourceMappingURL= bar22.js \n", "bar21.js", "bar22.js");
20493 TEST(GetOwnPropertyDescriptor) {
20495 v8::Isolate* isolate = env->GetIsolate();
20496 v8::HandleScope scope(isolate);
20498 "var x = { value : 13};"
20499 "Object.defineProperty(x, 'p0', {value : 12});"
20500 "Object.defineProperty(x, 'p1', {"
20501 " set : function(value) { this.value = value; },"
20502 " get : function() { return this.value; },"
20504 Local<Object> x = Local<Object>::Cast(env->Global()->Get(v8_str("x")));
20505 Local<Value> desc = x->GetOwnPropertyDescriptor(v8_str("no_prop"));
20506 CHECK(desc->IsUndefined());
20507 desc = x->GetOwnPropertyDescriptor(v8_str("p0"));
20508 CHECK(v8_num(12)->Equals(Local<Object>::Cast(desc)->Get(v8_str("value"))));
20509 desc = x->GetOwnPropertyDescriptor(v8_str("p1"));
20510 Local<Function> set =
20511 Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("set")));
20512 Local<Function> get =
20513 Local<Function>::Cast(Local<Object>::Cast(desc)->Get(v8_str("get")));
20514 CHECK(v8_num(13)->Equals(get->Call(x, 0, NULL)));
20515 Handle<Value> args[] = { v8_num(14) };
20516 set->Call(x, 1, args);
20517 CHECK(v8_num(14)->Equals(get->Call(x, 0, NULL)));
20521 TEST(Regress411877) {
20522 v8::Isolate* isolate = CcTest::isolate();
20523 v8::HandleScope handle_scope(isolate);
20524 v8::Handle<v8::ObjectTemplate> object_template =
20525 v8::ObjectTemplate::New(isolate);
20526 object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20528 v8::Handle<Context> context = Context::New(isolate);
20529 v8::Context::Scope context_scope(context);
20531 context->Global()->Set(v8_str("o"), object_template->NewInstance());
20532 CompileRun("Object.getOwnPropertyNames(o)");
20536 TEST(GetHiddenPropertyTableAfterAccessCheck) {
20537 v8::Isolate* isolate = CcTest::isolate();
20538 v8::HandleScope handle_scope(isolate);
20539 v8::Handle<v8::ObjectTemplate> object_template =
20540 v8::ObjectTemplate::New(isolate);
20541 object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20543 v8::Handle<Context> context = Context::New(isolate);
20544 v8::Context::Scope context_scope(context);
20546 v8::Handle<v8::Object> obj = object_template->NewInstance();
20547 obj->Set(v8_str("key"), v8_str("value"));
20548 obj->Delete(v8_str("key"));
20550 obj->SetHiddenValue(v8_str("hidden key 2"), v8_str("hidden value 2"));
20554 TEST(Regress411793) {
20555 v8::Isolate* isolate = CcTest::isolate();
20556 v8::HandleScope handle_scope(isolate);
20557 v8::Handle<v8::ObjectTemplate> object_template =
20558 v8::ObjectTemplate::New(isolate);
20559 object_template->SetAccessCheckCallbacks(AccessCounter, NULL);
20561 v8::Handle<Context> context = Context::New(isolate);
20562 v8::Context::Scope context_scope(context);
20564 context->Global()->Set(v8_str("o"), object_template->NewInstance());
20566 "Object.defineProperty(o, 'key', "
20567 " { get: function() {}, set: function() {} });");
20570 class TestSourceStream : public v8::ScriptCompiler::ExternalSourceStream {
20572 explicit TestSourceStream(const char** chunks) : chunks_(chunks), index_(0) {}
20574 virtual size_t GetMoreData(const uint8_t** src) {
20575 // Unlike in real use cases, this function will never block.
20576 if (chunks_[index_] == NULL) {
20579 // Copy the data, since the caller takes ownership of it.
20580 size_t len = strlen(chunks_[index_]);
20581 // We don't need to zero-terminate since we return the length.
20582 uint8_t* copy = new uint8_t[len];
20583 memcpy(copy, chunks_[index_], len);
20589 // Helper for constructing a string from chunks (the compilation needs it
20591 static char* FullSourceString(const char** chunks) {
20592 size_t total_len = 0;
20593 for (size_t i = 0; chunks[i] != NULL; ++i) {
20594 total_len += strlen(chunks[i]);
20596 char* full_string = new char[total_len + 1];
20598 for (size_t i = 0; chunks[i] != NULL; ++i) {
20599 size_t len = strlen(chunks[i]);
20600 memcpy(full_string + offset, chunks[i], len);
20603 full_string[total_len] = 0;
20604 return full_string;
20608 const char** chunks_;
20613 // Helper function for running streaming tests.
20614 void RunStreamingTest(const char** chunks,
20615 v8::ScriptCompiler::StreamedSource::Encoding encoding =
20616 v8::ScriptCompiler::StreamedSource::ONE_BYTE,
20617 bool expected_success = true,
20618 const char* expected_source_url = NULL,
20619 const char* expected_source_mapping_url = NULL) {
20621 v8::Isolate* isolate = env->GetIsolate();
20622 v8::HandleScope scope(isolate);
20623 v8::TryCatch try_catch(isolate);
20625 v8::ScriptCompiler::StreamedSource source(new TestSourceStream(chunks),
20627 v8::ScriptCompiler::ScriptStreamingTask* task =
20628 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
20630 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
20631 // task here in the main thread.
20635 // Possible errors are only produced while compiling.
20636 CHECK_EQ(false, try_catch.HasCaught());
20638 v8::ScriptOrigin origin(v8_str("http://foo.com"));
20639 char* full_source = TestSourceStream::FullSourceString(chunks);
20640 v8::Handle<Script> script = v8::ScriptCompiler::Compile(
20641 isolate, &source, v8_str(full_source), origin);
20642 if (expected_success) {
20643 CHECK(!script.IsEmpty());
20644 v8::Handle<Value> result(script->Run());
20645 // All scripts are supposed to return the fixed value 13 when ran.
20646 CHECK_EQ(13, result->Int32Value());
20647 CheckMagicComments(script, expected_source_url,
20648 expected_source_mapping_url);
20650 CHECK(script.IsEmpty());
20651 CHECK(try_catch.HasCaught());
20653 delete[] full_source;
20657 TEST(StreamingSimpleScript) {
20658 // This script is unrealistically small, since no one chunk is enough to fill
20659 // the backing buffer of Scanner, let alone overflow it.
20660 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
20662 RunStreamingTest(chunks);
20666 TEST(StreamingBiggerScript) {
20667 const char* chunk1 =
20668 "function foo() {\n"
20669 " // Make this chunk sufficiently long so that it will overflow the\n"
20670 " // backing buffer of the Scanner.\n"
20672 " var result = 0;\n"
20673 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20675 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20677 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20679 " for (i = 0; i < 13; ++i) { result = result + 1; }\n"
20680 " return result;\n"
20682 const char* chunks[] = {chunk1, "foo(); ", NULL};
20683 RunStreamingTest(chunks);
20687 TEST(StreamingScriptWithParseError) {
20688 // Test that parse errors from streamed scripts are propagated correctly.
20691 " // This will result in a parse error.\n"
20692 " var if else then foo";
20693 char chunk2[] = " 13\n";
20694 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20696 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE,
20699 // Test that the next script succeeds normally.
20702 " // This will be parsed successfully.\n"
20703 " function foo() { return ";
20704 char chunk2[] = " 13; }\n";
20705 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20707 RunStreamingTest(chunks);
20712 TEST(StreamingUtf8Script) {
20713 // We'd want to write \uc481 instead of \xec\x92\x81, but Windows compilers
20715 const char* chunk1 =
20716 "function foo() {\n"
20717 " // This function will contain an UTF-8 character which is not in\n"
20719 " var foob\xec\x92\x81r = 13;\n"
20720 " return foob\xec\x92\x81r;\n"
20722 const char* chunks[] = {chunk1, "foo(); ", NULL};
20723 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20727 TEST(StreamingUtf8ScriptWithSplitCharactersSanityCheck) {
20728 // A sanity check to prove that the approach of splitting UTF-8
20729 // characters is correct. Here is an UTF-8 character which will take three
20731 const char* reference = "\xec\x92\x81";
20732 CHECK(3u == strlen(reference)); // NOLINT - no CHECK_EQ for unsigned.
20735 "function foo() {\n"
20736 " // This function will contain an UTF-8 character which is not in\n"
20741 " return foob\xec\x92\x81r;\n"
20743 for (int i = 0; i < 3; ++i) {
20744 chunk2[i] = reference[i];
20746 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20747 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20751 TEST(StreamingUtf8ScriptWithSplitCharacters) {
20752 // Stream data where a multi-byte UTF-8 character is split between two data
20754 const char* reference = "\xec\x92\x81";
20756 "function foo() {\n"
20757 " // This function will contain an UTF-8 character which is not in\n"
20762 " return foob\xec\x92\x81r;\n"
20764 chunk1[strlen(chunk1) - 1] = reference[0];
20765 chunk2[0] = reference[1];
20766 chunk2[1] = reference[2];
20767 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20768 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20772 TEST(StreamingUtf8ScriptWithSplitCharactersValidEdgeCases) {
20773 // Tests edge cases which should still be decoded correctly.
20775 // Case 1: a chunk contains only bytes for a split character (and no other
20776 // data). This kind of a chunk would be exceptionally small, but we should
20777 // still decode it correctly.
20778 const char* reference = "\xec\x92\x81";
20779 // The small chunk is at the beginning of the split character
20782 "function foo() {\n"
20783 " // This function will contain an UTF-8 character which is not in\n"
20786 char chunk2[] = "XX";
20789 " return foob\xec\x92\x81r;\n"
20791 chunk2[0] = reference[0];
20792 chunk2[1] = reference[1];
20793 chunk3[0] = reference[2];
20794 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20795 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20797 // The small chunk is at the end of a character
20800 "function foo() {\n"
20801 " // This function will contain an UTF-8 character which is not in\n"
20804 char chunk2[] = "XX";
20807 " return foob\xec\x92\x81r;\n"
20809 chunk1[strlen(chunk1) - 1] = reference[0];
20810 chunk2[0] = reference[1];
20811 chunk2[1] = reference[2];
20812 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20813 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20815 // Case 2: the script ends with a multi-byte character. Make sure that it's
20816 // decoded correctly and not just ignored.
20819 "var foob\xec\x92\x81 = 13;\n"
20820 "foob\xec\x92\x81";
20821 const char* chunks[] = {chunk1, NULL};
20822 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20827 TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) {
20828 // Test cases where a UTF-8 character is split over several chunks. Those
20829 // cases are not supported (the embedder should give the data in big enough
20830 // chunks), but we shouldn't crash, just produce a parse error.
20831 const char* reference = "\xec\x92\x81";
20833 "function foo() {\n"
20834 " // This function will contain an UTF-8 character which is not in\n"
20837 char chunk2[] = "X";
20840 " return foob\xec\x92\x81r;\n"
20842 chunk1[strlen(chunk1) - 1] = reference[0];
20843 chunk2[0] = reference[1];
20844 chunk3[0] = reference[2];
20845 const char* chunks[] = {chunk1, chunk2, chunk3, "foo();", NULL};
20847 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
20851 TEST(StreamingProducesParserCache) {
20852 i::FLAG_min_preparse_length = 0;
20853 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ",
20857 v8::Isolate* isolate = env->GetIsolate();
20858 v8::HandleScope scope(isolate);
20860 v8::ScriptCompiler::StreamedSource source(
20861 new TestSourceStream(chunks),
20862 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
20863 v8::ScriptCompiler::ScriptStreamingTask* task =
20864 v8::ScriptCompiler::StartStreamingScript(
20865 isolate, &source, v8::ScriptCompiler::kProduceParserCache);
20867 // TestSourceStream::GetMoreData won't block, so it's OK to just run the
20868 // task here in the main thread.
20872 const v8::ScriptCompiler::CachedData* cached_data = source.GetCachedData();
20873 CHECK(cached_data != NULL);
20874 CHECK(cached_data->data != NULL);
20875 CHECK(!cached_data->rejected);
20876 CHECK_GT(cached_data->length, 0);
20880 TEST(StreamingWithDebuggingEnabledLate) {
20881 // The streaming parser can only parse lazily, i.e. inner functions are not
20882 // fully parsed. However, we may compile inner functions eagerly when
20883 // debugging. Make sure that we can deal with this when turning on debugging
20884 // after streaming parser has already finished parsing.
20885 i::FLAG_min_preparse_length = 0;
20886 const char* chunks[] = {"with({x:1}) {",
20887 " var foo = function foo(y) {",
20895 v8::Isolate* isolate = env->GetIsolate();
20896 v8::HandleScope scope(isolate);
20897 v8::TryCatch try_catch(isolate);
20899 v8::ScriptCompiler::StreamedSource source(
20900 new TestSourceStream(chunks),
20901 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
20902 v8::ScriptCompiler::ScriptStreamingTask* task =
20903 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
20908 CHECK(!try_catch.HasCaught());
20910 v8::ScriptOrigin origin(v8_str("http://foo.com"));
20911 char* full_source = TestSourceStream::FullSourceString(chunks);
20915 v8::Handle<Script> script = v8::ScriptCompiler::Compile(
20916 isolate, &source, v8_str(full_source), origin);
20918 Maybe<uint32_t> result =
20919 script->Run(env.local()).ToLocalChecked()->Uint32Value(env.local());
20920 CHECK_EQ(3U, result.FromMaybe(0));
20922 delete[] full_source;
20928 TEST(StreamingScriptWithInvalidUtf8) {
20929 // Regression test for a crash: test that invalid UTF-8 bytes in the end of a
20930 // chunk don't produce a crash.
20931 const char* reference = "\xec\x92\x81\x80\x80";
20933 "function foo() {\n"
20934 " // This function will contain an UTF-8 character which is not in\n"
20936 " var foobXXXXX"; // Too many bytes which look like incomplete chars!
20939 " return foob\xec\x92\x81\x80\x80r;\n"
20941 for (int i = 0; i < 5; ++i) chunk1[strlen(chunk1) - 5 + i] = reference[i];
20943 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20944 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, false);
20948 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit) {
20949 // Regression test: Stream data where there are several multi-byte UTF-8
20950 // characters in a sequence and one of them is split between two data chunks.
20951 const char* reference = "\xec\x92\x81";
20953 "function foo() {\n"
20954 " // This function will contain an UTF-8 character which is not in\n"
20956 " var foob\xec\x92\x81X";
20959 " return foob\xec\x92\x81\xec\x92\x81r;\n"
20961 chunk1[strlen(chunk1) - 1] = reference[0];
20962 chunk2[0] = reference[1];
20963 chunk2[1] = reference[2];
20964 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20965 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20969 TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) {
20970 // Another regression test, similar to the previous one. The difference is
20971 // that the split character is not the last one in the sequence.
20972 const char* reference = "\xec\x92\x81";
20974 "function foo() {\n"
20975 " // This function will contain an UTF-8 character which is not in\n"
20979 "XX\xec\x92\x81r = 13;\n"
20980 " return foob\xec\x92\x81\xec\x92\x81r;\n"
20982 chunk1[strlen(chunk1) - 1] = reference[0];
20983 chunk2[0] = reference[1];
20984 chunk2[1] = reference[2];
20985 const char* chunks[] = {chunk1, chunk2, "foo();", NULL};
20986 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8);
20990 TEST(StreamingWithHarmonyScopes) {
20991 // Don't use RunStreamingTest here so that both scripts get to use the same
20992 // LocalContext and HandleScope.
20994 v8::Isolate* isolate = env->GetIsolate();
20995 v8::HandleScope scope(isolate);
20997 // First, run a script with a let variable.
20998 CompileRun("\"use strict\"; let x = 1;");
21000 // Then stream a script which (erroneously) tries to introduce the same
21002 const char* chunks[] = {"\"use strict\"; let x = 2;", NULL};
21004 v8::TryCatch try_catch(isolate);
21005 v8::ScriptCompiler::StreamedSource source(
21006 new TestSourceStream(chunks),
21007 v8::ScriptCompiler::StreamedSource::ONE_BYTE);
21008 v8::ScriptCompiler::ScriptStreamingTask* task =
21009 v8::ScriptCompiler::StartStreamingScript(isolate, &source);
21013 // Parsing should succeed (the script will be parsed and compiled in a context
21014 // independent way, so the error is not detected).
21015 CHECK_EQ(false, try_catch.HasCaught());
21017 v8::ScriptOrigin origin(v8_str("http://foo.com"));
21018 char* full_source = TestSourceStream::FullSourceString(chunks);
21019 v8::Handle<Script> script = v8::ScriptCompiler::Compile(
21020 isolate, &source, v8_str(full_source), origin);
21021 CHECK(!script.IsEmpty());
21022 CHECK_EQ(false, try_catch.HasCaught());
21024 // Running the script exposes the error.
21025 v8::Handle<Value> result(script->Run());
21026 CHECK(result.IsEmpty());
21027 CHECK(try_catch.HasCaught());
21028 delete[] full_source;
21033 v8::Isolate::CreateParams create_params;
21034 create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
21036 const char* source = "Math.sqrt(4)";
21037 const char* origin = "code cache test";
21038 v8::ScriptCompiler::CachedData* cache;
21040 v8::Isolate* isolate1 = v8::Isolate::New(create_params);
21042 v8::Isolate::Scope iscope(isolate1);
21043 v8::HandleScope scope(isolate1);
21044 v8::Local<v8::Context> context = v8::Context::New(isolate1);
21045 v8::Context::Scope cscope(context);
21046 v8::Local<v8::String> source_string = v8_str(source);
21047 v8::ScriptOrigin script_origin(v8_str(origin));
21048 v8::ScriptCompiler::Source source(source_string, script_origin);
21049 v8::ScriptCompiler::CompileOptions option =
21050 v8::ScriptCompiler::kProduceCodeCache;
21051 v8::ScriptCompiler::Compile(context, &source, option).ToLocalChecked();
21052 int length = source.GetCachedData()->length;
21053 uint8_t* cache_data = new uint8_t[length];
21054 memcpy(cache_data, source.GetCachedData()->data, length);
21055 cache = new v8::ScriptCompiler::CachedData(
21056 cache_data, length, v8::ScriptCompiler::CachedData::BufferOwned);
21058 isolate1->Dispose();
21060 v8::Isolate* isolate2 = v8::Isolate::New(create_params);
21062 v8::Isolate::Scope iscope(isolate2);
21063 v8::HandleScope scope(isolate2);
21064 v8::Local<v8::Context> context = v8::Context::New(isolate2);
21065 v8::Context::Scope cscope(context);
21066 v8::Local<v8::String> source_string = v8_str(source);
21067 v8::ScriptOrigin script_origin(v8_str(origin));
21068 v8::ScriptCompiler::Source source(source_string, script_origin, cache);
21069 v8::ScriptCompiler::CompileOptions option =
21070 v8::ScriptCompiler::kConsumeCodeCache;
21071 v8::Local<v8::Script> script;
21073 i::DisallowCompilation no_compile(
21074 reinterpret_cast<i::Isolate*>(isolate2));
21075 script = v8::ScriptCompiler::Compile(context, &source, option)
21078 CHECK_EQ(2, script->Run()->ToInt32(isolate2)->Int32Value());
21080 isolate2->Dispose();
21084 void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) {
21085 const char* garbage = "garbage garbage garbage garbage garbage garbage";
21086 const uint8_t* data = reinterpret_cast<const uint8_t*>(garbage);
21088 v8::ScriptCompiler::CachedData* cached_data =
21089 new v8::ScriptCompiler::CachedData(data, length);
21090 DCHECK(!cached_data->rejected);
21091 v8::ScriptOrigin origin(v8_str("origin"));
21092 v8::ScriptCompiler::Source source(v8_str("42"), origin, cached_data);
21093 v8::Handle<v8::Script> script =
21094 v8::ScriptCompiler::Compile(CcTest::isolate(), &source, option);
21095 CHECK(cached_data->rejected);
21096 CHECK_EQ(42, script->Run()->Int32Value());
21100 TEST(InvalidCacheData) {
21101 v8::V8::Initialize();
21102 v8::HandleScope scope(CcTest::isolate());
21103 LocalContext context;
21104 TestInvalidCacheData(v8::ScriptCompiler::kConsumeParserCache);
21105 TestInvalidCacheData(v8::ScriptCompiler::kConsumeCodeCache);
21109 TEST(ParserCacheRejectedGracefully) {
21110 i::FLAG_min_preparse_length = 0;
21111 v8::V8::Initialize();
21112 v8::HandleScope scope(CcTest::isolate());
21113 LocalContext context;
21114 // Produce valid cached data.
21115 v8::ScriptOrigin origin(v8_str("origin"));
21116 v8::Local<v8::String> source_str = v8_str("function foo() {}");
21117 v8::ScriptCompiler::Source source(source_str, origin);
21118 v8::Handle<v8::Script> script = v8::ScriptCompiler::Compile(
21119 CcTest::isolate(), &source, v8::ScriptCompiler::kProduceParserCache);
21120 CHECK(!script.IsEmpty());
21121 const v8::ScriptCompiler::CachedData* original_cached_data =
21122 source.GetCachedData();
21123 CHECK(original_cached_data != NULL);
21124 CHECK(original_cached_data->data != NULL);
21125 CHECK(!original_cached_data->rejected);
21126 CHECK_GT(original_cached_data->length, 0);
21127 // Recompiling the same script with it won't reject the data.
21129 v8::ScriptCompiler::Source source_with_cached_data(
21130 source_str, origin,
21131 new v8::ScriptCompiler::CachedData(original_cached_data->data,
21132 original_cached_data->length));
21133 v8::Handle<v8::Script> script =
21134 v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21135 v8::ScriptCompiler::kConsumeParserCache);
21136 CHECK(!script.IsEmpty());
21137 const v8::ScriptCompiler::CachedData* new_cached_data =
21138 source_with_cached_data.GetCachedData();
21139 CHECK(new_cached_data != NULL);
21140 CHECK(!new_cached_data->rejected);
21142 // Compile an incompatible script with the cached data. The new script doesn't
21143 // have the same starting position for the function as the old one, so the old
21144 // cached data will be incompatible with it and will be rejected.
21146 v8::Local<v8::String> incompatible_source_str =
21147 v8_str(" function foo() {}");
21148 v8::ScriptCompiler::Source source_with_cached_data(
21149 incompatible_source_str, origin,
21150 new v8::ScriptCompiler::CachedData(original_cached_data->data,
21151 original_cached_data->length));
21152 v8::Handle<v8::Script> script =
21153 v8::ScriptCompiler::Compile(CcTest::isolate(), &source_with_cached_data,
21154 v8::ScriptCompiler::kConsumeParserCache);
21155 CHECK(!script.IsEmpty());
21156 const v8::ScriptCompiler::CachedData* new_cached_data =
21157 source_with_cached_data.GetCachedData();
21158 CHECK(new_cached_data != NULL);
21159 CHECK(new_cached_data->rejected);
21164 TEST(StringConcatOverflow) {
21165 v8::V8::Initialize();
21166 v8::HandleScope scope(CcTest::isolate());
21167 RandomLengthOneByteResource* r =
21168 new RandomLengthOneByteResource(i::String::kMaxLength);
21169 v8::Local<v8::String> str = v8::String::NewExternal(CcTest::isolate(), r);
21170 CHECK(!str.IsEmpty());
21171 v8::TryCatch try_catch(CcTest::isolate());
21172 v8::Local<v8::String> result = v8::String::Concat(str, str);
21173 CHECK(result.IsEmpty());
21174 CHECK(!try_catch.HasCaught());
21178 TEST(TurboAsmDisablesNeuter) {
21179 v8::V8::Initialize();
21180 v8::HandleScope scope(CcTest::isolate());
21181 LocalContext context;
21182 bool should_be_neuterable = !i::FLAG_turbo_asm;
21184 "function Module(stdlib, foreign, heap) {"
21186 " var MEM32 = new stdlib.Int32Array(heap);"
21187 " function load() { return MEM32[0]; }"
21188 " return { load: load };"
21190 "var buffer = new ArrayBuffer(4);"
21191 "Module(this, {}, buffer).load();"
21194 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
21195 v8::Local<v8::ArrayBuffer> result = CompileRun(load).As<v8::ArrayBuffer>();
21196 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21198 const char* store =
21199 "function Module(stdlib, foreign, heap) {"
21201 " var MEM32 = new stdlib.Int32Array(heap);"
21202 " function store() { MEM32[0] = 0; }"
21203 " return { store: store };"
21205 "var buffer = new ArrayBuffer(4);"
21206 "Module(this, {}, buffer).store();"
21209 i::FLAG_turbo_osr = false; // TODO(titzer): test requires eager TF.
21210 result = CompileRun(store).As<v8::ArrayBuffer>();
21211 CHECK_EQ(should_be_neuterable, result->IsNeuterable());
21215 TEST(GetPrototypeAccessControl) {
21216 i::FLAG_allow_natives_syntax = true;
21217 v8::Isolate* isolate = CcTest::isolate();
21218 v8::HandleScope handle_scope(isolate);
21221 v8::Handle<v8::ObjectTemplate> obj_template =
21222 v8::ObjectTemplate::New(isolate);
21223 obj_template->SetAccessCheckCallbacks(AccessAlwaysBlocked, NULL);
21225 env->Global()->Set(v8_str("prohibited"), obj_template->NewInstance());
21228 "function f() { return %_GetPrototype(prohibited); }"
21229 "%OptimizeFunctionOnNextCall(f);"
21230 "f();")->IsNull());
21234 TEST(GetPrototypeHidden) {
21235 i::FLAG_allow_natives_syntax = true;
21236 v8::Isolate* isolate = CcTest::isolate();
21237 v8::HandleScope handle_scope(isolate);
21240 Handle<FunctionTemplate> t = FunctionTemplate::New(isolate);
21241 t->SetHiddenPrototype(true);
21242 Handle<Object> proto = t->GetFunction()->NewInstance();
21243 Handle<Object> object = Object::New(isolate);
21244 Handle<Object> proto2 = Object::New(isolate);
21245 object->SetPrototype(proto);
21246 proto->SetPrototype(proto2);
21248 env->Global()->Set(v8_str("object"), object);
21249 env->Global()->Set(v8_str("proto"), proto);
21250 env->Global()->Set(v8_str("proto2"), proto2);
21252 v8::Handle<v8::Value> result = CompileRun("%_GetPrototype(object)");
21253 CHECK(result->Equals(proto2));
21255 result = CompileRun(
21256 "function f() { return %_GetPrototype(object); }"
21257 "%OptimizeFunctionOnNextCall(f);"
21259 CHECK(result->Equals(proto2));
21263 TEST(ClassPrototypeCreationContext) {
21264 v8::Isolate* isolate = CcTest::isolate();
21265 v8::HandleScope handle_scope(isolate);
21268 Handle<Object> result = Handle<Object>::Cast(
21269 CompileRun("'use strict'; class Example { }; Example.prototype"));
21270 CHECK(env.local() == result->CreationContext());
21274 TEST(SimpleStreamingScriptWithSourceURL) {
21275 const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo();\n",
21276 "//# sourceURL=bar2.js\n", NULL};
21277 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21282 TEST(StreamingScriptWithSplitSourceURL) {
21283 const char* chunks[] = {"function foo() { ret", "urn 13; } f",
21284 "oo();\n//# sourceURL=b", "ar2.js\n", NULL};
21285 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true,
21290 TEST(StreamingScriptWithSourceMappingURLInTheMiddle) {
21291 const char* chunks[] = {"function foo() { ret", "urn 13; }\n//#",
21292 " sourceMappingURL=bar2.js\n", "foo();", NULL};
21293 RunStreamingTest(chunks, v8::ScriptCompiler::StreamedSource::UTF8, true, NULL,
21298 TEST(NewStringRangeError) {
21299 v8::Isolate* isolate = CcTest::isolate();
21300 v8::HandleScope handle_scope(isolate);
21301 const int length = i::String::kMaxLength + 1;
21302 const int buffer_size = length * sizeof(uint16_t);
21303 void* buffer = malloc(buffer_size);
21304 if (buffer == NULL) return;
21305 memset(buffer, 'A', buffer_size);
21307 v8::TryCatch try_catch(isolate);
21308 char* data = reinterpret_cast<char*>(buffer);
21309 CHECK(v8::String::NewFromUtf8(isolate, data, v8::String::kNormalString,
21310 length).IsEmpty());
21311 CHECK(!try_catch.HasCaught());
21314 v8::TryCatch try_catch(isolate);
21315 uint8_t* data = reinterpret_cast<uint8_t*>(buffer);
21316 CHECK(v8::String::NewFromOneByte(isolate, data, v8::String::kNormalString,
21317 length).IsEmpty());
21318 CHECK(!try_catch.HasCaught());
21321 v8::TryCatch try_catch(isolate);
21322 uint16_t* data = reinterpret_cast<uint16_t*>(buffer);
21323 CHECK(v8::String::NewFromTwoByte(isolate, data, v8::String::kNormalString,
21324 length).IsEmpty());
21325 CHECK(!try_catch.HasCaught());
21331 TEST(SealHandleScope) {
21332 v8::Isolate* isolate = CcTest::isolate();
21333 v8::HandleScope handle_scope(isolate);
21336 v8::SealHandleScope seal(isolate);
21339 v8::Local<v8::Object> obj = v8::Object::New(isolate);
21345 TEST(SealHandleScopeNested) {
21346 v8::Isolate* isolate = CcTest::isolate();
21347 v8::HandleScope handle_scope(isolate);
21350 v8::SealHandleScope seal(isolate);
21353 v8::HandleScope handle_scope(isolate);
21356 v8::Local<v8::Object> obj = v8::Object::New(isolate);
21363 static bool access_was_called = false;
21366 static bool AccessAlwaysAllowedWithFlag(Local<v8::Object> global,
21367 Local<Value> name, v8::AccessType type,
21368 Local<Value> data) {
21369 access_was_called = true;
21374 static bool AccessAlwaysBlockedWithFlag(Local<v8::Object> global,
21375 Local<Value> name, v8::AccessType type,
21376 Local<Value> data) {
21377 access_was_called = true;
21382 TEST(StrongModeAccessCheckAllowed) {
21383 i::FLAG_strong_mode = true;
21384 v8::Isolate* isolate = CcTest::isolate();
21385 v8::HandleScope handle_scope(isolate);
21386 v8::Handle<Value> value;
21387 access_was_called = false;
21389 v8::Handle<v8::ObjectTemplate> obj_template =
21390 v8::ObjectTemplate::New(isolate);
21392 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
21393 obj_template->SetAccessCheckCallbacks(AccessAlwaysAllowedWithFlag, NULL);
21395 // Create an environment
21396 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
21398 v8::Handle<v8::Object> global0 = context0->Global();
21399 global0->Set(v8_str("object"), obj_template->NewInstance());
21401 v8::TryCatch try_catch(isolate);
21402 value = CompileRun("'use strong'; object.x");
21403 CHECK(!try_catch.HasCaught());
21404 CHECK(!access_was_called);
21405 CHECK_EQ(42, value->Int32Value());
21408 v8::TryCatch try_catch(isolate);
21409 value = CompileRun("'use strong'; object.foo");
21410 CHECK(try_catch.HasCaught());
21411 CHECK(!access_was_called);
21414 v8::TryCatch try_catch(isolate);
21415 value = CompileRun("'use strong'; object[10]");
21416 CHECK(try_catch.HasCaught());
21417 CHECK(!access_was_called);
21420 // Create an environment
21421 v8::Local<Context> context1 = Context::New(isolate);
21423 v8::Handle<v8::Object> global1 = context1->Global();
21424 global1->Set(v8_str("object"), obj_template->NewInstance());
21426 v8::TryCatch try_catch(isolate);
21427 value = CompileRun("'use strong'; object.x");
21428 CHECK(!try_catch.HasCaught());
21429 CHECK(access_was_called);
21430 CHECK_EQ(42, value->Int32Value());
21432 access_was_called = false;
21434 v8::TryCatch try_catch(isolate);
21435 value = CompileRun("'use strong'; object.foo");
21436 CHECK(try_catch.HasCaught());
21437 CHECK(access_was_called);
21439 access_was_called = false;
21441 v8::TryCatch try_catch(isolate);
21442 value = CompileRun("'use strong'; object[10]");
21443 CHECK(try_catch.HasCaught());
21444 CHECK(access_was_called);
21452 TEST(StrongModeAccessCheckBlocked) {
21453 i::FLAG_strong_mode = true;
21454 v8::Isolate* isolate = CcTest::isolate();
21455 v8::HandleScope handle_scope(isolate);
21456 v8::Handle<Value> value;
21457 access_was_called = false;
21459 v8::Handle<v8::ObjectTemplate> obj_template =
21460 v8::ObjectTemplate::New(isolate);
21462 obj_template->Set(v8_str("x"), v8::Integer::New(isolate, 42));
21463 obj_template->SetAccessCheckCallbacks(AccessAlwaysBlockedWithFlag, NULL);
21465 // Create an environment
21466 v8::Local<Context> context0 = Context::New(isolate, NULL, obj_template);
21468 v8::Handle<v8::Object> global0 = context0->Global();
21469 global0->Set(v8_str("object"), obj_template->NewInstance());
21471 v8::TryCatch try_catch(isolate);
21472 value = CompileRun("'use strong'; object.x");
21473 CHECK(!try_catch.HasCaught());
21474 CHECK(!access_was_called);
21475 CHECK_EQ(42, value->Int32Value());
21478 v8::TryCatch try_catch(isolate);
21479 value = CompileRun("'use strong'; object.foo");
21480 CHECK(try_catch.HasCaught());
21481 CHECK(!access_was_called);
21484 v8::TryCatch try_catch(isolate);
21485 value = CompileRun("'use strong'; object[10]");
21486 CHECK(try_catch.HasCaught());
21487 CHECK(!access_was_called);
21490 // Create an environment
21491 v8::Local<Context> context1 = Context::New(isolate);
21493 v8::Handle<v8::Object> global1 = context1->Global();
21494 global1->Set(v8_str("object"), obj_template->NewInstance());
21496 v8::TryCatch try_catch(isolate);
21497 value = CompileRun("'use strong'; object.x");
21498 CHECK(try_catch.HasCaught());
21499 CHECK(access_was_called);
21501 access_was_called = false;
21503 v8::TryCatch try_catch(isolate);
21504 value = CompileRun("'use strong'; object.foo");
21505 CHECK(try_catch.HasCaught());
21506 CHECK(access_was_called);
21508 access_was_called = false;
21510 v8::TryCatch try_catch(isolate);
21511 value = CompileRun("'use strong'; object[10]");
21512 CHECK(try_catch.HasCaught());
21513 CHECK(access_was_called);
21521 TEST(StrongModeArityCallFromApi) {
21522 i::FLAG_strong_mode = true;
21524 v8::Isolate* isolate = env->GetIsolate();
21525 v8::HandleScope scope(isolate);
21526 Local<Function> fun;
21528 v8::TryCatch try_catch(isolate);
21529 fun = Local<Function>::Cast(CompileRun(
21530 "function f(x) { 'use strong'; }"
21533 CHECK(!try_catch.HasCaught());
21537 v8::TryCatch try_catch(isolate);
21538 fun->Call(v8::Undefined(isolate), 0, nullptr);
21539 CHECK(try_catch.HasCaught());
21543 v8::TryCatch try_catch(isolate);
21544 v8::Handle<Value> args[] = {v8_num(42)};
21545 fun->Call(v8::Undefined(isolate), arraysize(args), args);
21546 CHECK(!try_catch.HasCaught());
21550 v8::TryCatch try_catch(isolate);
21551 v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
21552 fun->Call(v8::Undefined(isolate), arraysize(args), args);
21553 CHECK(!try_catch.HasCaught());
21558 TEST(StrongModeArityCallFromApi2) {
21559 i::FLAG_strong_mode = true;
21561 v8::Isolate* isolate = env->GetIsolate();
21562 v8::HandleScope scope(isolate);
21563 Local<Function> fun;
21565 v8::TryCatch try_catch(isolate);
21566 fun = Local<Function>::Cast(CompileRun(
21571 CHECK(!try_catch.HasCaught());
21575 v8::TryCatch try_catch(isolate);
21576 fun->Call(v8::Undefined(isolate), 0, nullptr);
21577 CHECK(try_catch.HasCaught());
21581 v8::TryCatch try_catch(isolate);
21582 v8::Handle<Value> args[] = {v8_num(42)};
21583 fun->Call(v8::Undefined(isolate), arraysize(args), args);
21584 CHECK(!try_catch.HasCaught());
21588 v8::TryCatch try_catch(isolate);
21589 v8::Handle<Value> args[] = {v8_num(42), v8_num(555)};
21590 fun->Call(v8::Undefined(isolate), arraysize(args), args);
21591 CHECK(!try_catch.HasCaught());
21596 TEST(StrongObjectDelete) {
21597 i::FLAG_strong_mode = true;
21599 v8::Isolate* isolate = env->GetIsolate();
21600 v8::HandleScope scope(isolate);
21603 v8::TryCatch try_catch;
21604 obj = Local<Object>::Cast(CompileRun(
21607 CHECK(!try_catch.HasCaught());
21609 obj->ForceSet(v8_str("foo"), v8_num(1), v8::None);
21610 obj->ForceSet(v8_str("2"), v8_num(1), v8::None);
21611 CHECK(obj->HasOwnProperty(v8_str("foo")));
21612 CHECK(obj->HasOwnProperty(v8_str("2")));
21613 CHECK(!obj->Delete(v8_str("foo")));
21614 CHECK(!obj->Delete(2));
21618 static void ExtrasExportsTestRuntimeFunction(
21619 const v8::FunctionCallbackInfo<v8::Value>& args) {
21620 CHECK_EQ(3, args[0]->Int32Value());
21621 args.GetReturnValue().Set(v8_num(7));
21625 TEST(ExtrasExportsObject) {
21626 v8::Isolate* isolate = CcTest::isolate();
21627 v8::HandleScope handle_scope(isolate);
21630 // standalone.gypi ensures we include the test-extra.js file, which should
21631 // export the tested functions.
21632 v8::Local<v8::Object> binding = env->GetExtrasBindingObject();
21635 binding->Get(v8_str("testExtraShouldReturnFive")).As<v8::Function>();
21636 auto undefined = v8::Undefined(isolate);
21637 auto result = func->Call(undefined, 0, {}).As<v8::Number>();
21638 CHECK_EQ(5, result->Int32Value());
21640 v8::Handle<v8::FunctionTemplate> runtimeFunction =
21641 v8::FunctionTemplate::New(isolate, ExtrasExportsTestRuntimeFunction);
21642 binding->Set(v8_str("runtime"), runtimeFunction->GetFunction());
21644 binding->Get(v8_str("testExtraShouldCallToRuntime")).As<v8::Function>();
21645 result = func->Call(undefined, 0, {}).As<v8::Number>();
21646 CHECK_EQ(7, result->Int32Value());
21651 v8::Isolate* isolate = CcTest::isolate();
21652 v8::HandleScope handle_scope(isolate);
21655 v8::Local<v8::Map> map = v8::Map::New(isolate);
21656 CHECK(map->IsObject());
21657 CHECK(map->IsMap());
21658 CHECK(map->GetPrototype()->StrictEquals(CompileRun("Map.prototype")));
21659 CHECK_EQ(0U, map->Size());
21661 v8::Local<v8::Value> val = CompileRun("new Map([[1, 2], [3, 4]])");
21662 CHECK(val->IsMap());
21663 map = v8::Local<v8::Map>::Cast(val);
21664 CHECK_EQ(2U, map->Size());
21666 v8::Local<v8::Array> contents = map->AsArray();
21667 CHECK_EQ(4U, contents->Length());
21668 CHECK_EQ(1, contents->Get(0).As<v8::Int32>()->Value());
21669 CHECK_EQ(2, contents->Get(1).As<v8::Int32>()->Value());
21670 CHECK_EQ(3, contents->Get(2).As<v8::Int32>()->Value());
21671 CHECK_EQ(4, contents->Get(3).As<v8::Int32>()->Value());
21673 CHECK_EQ(2U, map->Size());
21675 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
21676 CHECK(map->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
21678 CHECK(!map->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
21679 CHECK(!map->Has(env.local(), map).FromJust());
21681 CHECK_EQ(2, map->Get(env.local(), v8::Integer::New(isolate, 1))
21684 CHECK_EQ(4, map->Get(env.local(), v8::Integer::New(isolate, 3))
21688 CHECK(map->Get(env.local(), v8::Integer::New(isolate, 42))
21692 CHECK(!map->Set(env.local(), map, map).IsEmpty());
21693 CHECK_EQ(3U, map->Size());
21694 CHECK(map->Has(env.local(), map).FromJust());
21696 CHECK(map->Delete(env.local(), map).FromJust());
21697 CHECK_EQ(2U, map->Size());
21698 CHECK(!map->Has(env.local(), map).FromJust());
21699 CHECK(!map->Delete(env.local(), map).FromJust());
21702 CHECK_EQ(0U, map->Size());
21707 v8::Isolate* isolate = CcTest::isolate();
21708 v8::HandleScope handle_scope(isolate);
21711 v8::Local<v8::Set> set = v8::Set::New(isolate);
21712 CHECK(set->IsObject());
21713 CHECK(set->IsSet());
21714 CHECK(set->GetPrototype()->StrictEquals(CompileRun("Set.prototype")));
21715 CHECK_EQ(0U, set->Size());
21717 v8::Local<v8::Value> val = CompileRun("new Set([1, 2])");
21718 CHECK(val->IsSet());
21719 set = v8::Local<v8::Set>::Cast(val);
21720 CHECK_EQ(2U, set->Size());
21722 v8::Local<v8::Array> keys = set->AsArray();
21723 CHECK_EQ(2U, keys->Length());
21724 CHECK_EQ(1, keys->Get(0).As<v8::Int32>()->Value());
21725 CHECK_EQ(2, keys->Get(1).As<v8::Int32>()->Value());
21727 CHECK_EQ(2U, set->Size());
21729 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 1)).FromJust());
21730 CHECK(set->Has(env.local(), v8::Integer::New(isolate, 2)).FromJust());
21732 CHECK(!set->Has(env.local(), v8::Integer::New(isolate, 3)).FromJust());
21733 CHECK(!set->Has(env.local(), set).FromJust());
21735 CHECK(!set->Add(env.local(), set).IsEmpty());
21736 CHECK_EQ(3U, set->Size());
21737 CHECK(set->Has(env.local(), set).FromJust());
21739 CHECK(set->Delete(env.local(), set).FromJust());
21740 CHECK_EQ(2U, set->Size());
21741 CHECK(!set->Has(env.local(), set).FromJust());
21742 CHECK(!set->Delete(env.local(), set).FromJust());
21745 CHECK_EQ(0U, set->Size());
21749 TEST(CompatibleReceiverCheckOnCachedICHandler) {
21750 v8::Isolate* isolate = CcTest::isolate();
21751 v8::HandleScope scope(isolate);
21752 v8::Local<v8::FunctionTemplate> parent = FunctionTemplate::New(isolate);
21753 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, parent);
21755 v8::FunctionTemplate::New(isolate, Returns42, Local<Value>(), signature);
21756 parent->PrototypeTemplate()->SetAccessorProperty(v8_str("age"), returns_42);
21757 v8::Local<v8::FunctionTemplate> child = v8::FunctionTemplate::New(isolate);
21758 child->Inherit(parent);
21760 env->Global()->Set(v8_str("Child"), child->GetFunction());
21762 // Make sure there's a compiled stub for "Child.prototype.age" in the cache.
21764 "var real = new Child();\n"
21765 "for (var i = 0; i < 3; ++i) {\n"
21769 // Check that the cached stub is never used.
21771 "var fake = Object.create(Child.prototype);\n"
21772 "var result = 0;\n"
21773 "function test(d) {\n"
21774 " if (d == 3) return;\n"
21787 class FutexInterruptionThread : public v8::base::Thread {
21789 explicit FutexInterruptionThread(v8::Isolate* isolate)
21790 : Thread(Options("FutexInterruptionThread")), isolate_(isolate) {}
21792 virtual void Run() {
21793 // Wait a bit before terminating.
21794 v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
21795 v8::V8::TerminateExecution(isolate_);
21799 v8::Isolate* isolate_;
21803 TEST(FutexInterruption) {
21804 i::FLAG_harmony_sharedarraybuffer = true;
21805 i::FLAG_harmony_atomics = true;
21806 v8::Isolate* isolate = CcTest::isolate();
21807 v8::HandleScope scope(isolate);
21810 FutexInterruptionThread timeout_thread(isolate);
21812 v8::TryCatch try_catch(CcTest::isolate());
21813 timeout_thread.Start();
21816 "var ab = new SharedArrayBuffer(4);"
21817 "var i32a = new Int32Array(ab);"
21818 "Atomics.futexWait(i32a, 0, 0);");
21819 CHECK(try_catch.HasTerminated());
21823 TEST(EstimatedContextSize) {
21824 v8::Isolate* isolate = CcTest::isolate();
21825 v8::HandleScope scope(isolate);
21827 CHECK(50000 < env->EstimatedSize());