| OLD | NEW |
| 1 // Copyright 2007-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2007-2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 | 31 |
| 32 #include "api.h" | 32 #include "api.h" |
| 33 #include "compilation-cache.h" | 33 #include "compilation-cache.h" |
| 34 #include "execution.h" | 34 #include "execution.h" |
| 35 #include "snapshot.h" | 35 #include "snapshot.h" |
| 36 #include "platform.h" | 36 #include "platform.h" |
| 37 #include "top.h" | 37 #include "top.h" |
| 38 #include "utils.h" | 38 #include "utils.h" |
| 39 #include "cctest.h" | 39 #include "cctest.h" |
| 40 | 40 |
| 41 static const bool kLogThreading = false; |
| 42 |
| 41 static bool IsNaN(double x) { | 43 static bool IsNaN(double x) { |
| 42 #ifdef WIN32 | 44 #ifdef WIN32 |
| 43 return _isnan(x); | 45 return _isnan(x); |
| 44 #else | 46 #else |
| 45 return isnan(x); | 47 return isnan(x); |
| 46 #endif | 48 #endif |
| 47 } | 49 } |
| 48 | 50 |
| 49 using ::v8::ObjectTemplate; | 51 using ::v8::ObjectTemplate; |
| 50 using ::v8::Value; | 52 using ::v8::Value; |
| 51 using ::v8::Context; | 53 using ::v8::Context; |
| 52 using ::v8::Local; | 54 using ::v8::Local; |
| 53 using ::v8::String; | 55 using ::v8::String; |
| 54 using ::v8::Script; | 56 using ::v8::Script; |
| 55 using ::v8::Function; | 57 using ::v8::Function; |
| 56 using ::v8::AccessorInfo; | 58 using ::v8::AccessorInfo; |
| 57 using ::v8::Extension; | 59 using ::v8::Extension; |
| 58 | 60 |
| 59 namespace i = ::v8::internal; | 61 namespace i = ::v8::internal; |
| 60 | 62 |
| 61 static Local<Value> v8_num(double x) { | |
| 62 return v8::Number::New(x); | |
| 63 } | |
| 64 | |
| 65 | |
| 66 static Local<String> v8_str(const char* x) { | |
| 67 return String::New(x); | |
| 68 } | |
| 69 | |
| 70 | |
| 71 static Local<Script> v8_compile(const char* x) { | |
| 72 return Script::Compile(v8_str(x)); | |
| 73 } | |
| 74 | |
| 75 | |
| 76 // A LocalContext holds a reference to a v8::Context. | |
| 77 class LocalContext { | |
| 78 public: | |
| 79 LocalContext(v8::ExtensionConfiguration* extensions = 0, | |
| 80 v8::Handle<ObjectTemplate> global_template = | |
| 81 v8::Handle<ObjectTemplate>(), | |
| 82 v8::Handle<Value> global_object = v8::Handle<Value>()) | |
| 83 : context_(Context::New(extensions, global_template, global_object)) { | |
| 84 context_->Enter(); | |
| 85 } | |
| 86 | |
| 87 virtual ~LocalContext() { | |
| 88 context_->Exit(); | |
| 89 context_.Dispose(); | |
| 90 } | |
| 91 | |
| 92 Context* operator->() { return *context_; } | |
| 93 Context* operator*() { return *context_; } | |
| 94 Local<Context> local() { return Local<Context>::New(context_); } | |
| 95 bool IsReady() { return !context_.IsEmpty(); } | |
| 96 | |
| 97 private: | |
| 98 v8::Persistent<Context> context_; | |
| 99 }; | |
| 100 | |
| 101 | |
| 102 // Switches between all the Api tests using the threading support. | |
| 103 // In order to get a surprising but repeatable pattern of thread | |
| 104 // switching it has extra semaphores to control the order in which | |
| 105 // the tests alternate, not relying solely on the big V8 lock. | |
| 106 // | |
| 107 // A test is augmented with calls to ApiTestFuzzer::Fuzz() in its | |
| 108 // callbacks. This will have no effect when we are not running the | |
| 109 // thread fuzzing test. In the thread fuzzing test it will | |
| 110 // pseudorandomly select a successor thread and switch execution | |
| 111 // to that thread, suspending the current test. | |
| 112 class ApiTestFuzzer: public v8::internal::Thread { | |
| 113 public: | |
| 114 void CallTest(); | |
| 115 explicit ApiTestFuzzer(int num) | |
| 116 : test_number_(num), | |
| 117 gate_(v8::internal::OS::CreateSemaphore(0)), | |
| 118 active_(true) { | |
| 119 } | |
| 120 ~ApiTestFuzzer() { delete gate_; } | |
| 121 | |
| 122 // The ApiTestFuzzer is also a Thread, so it has a Run method. | |
| 123 virtual void Run(); | |
| 124 | |
| 125 enum PartOfTest { FIRST_PART, SECOND_PART }; | |
| 126 | |
| 127 static void Setup(PartOfTest part); | |
| 128 static void RunAllTests(); | |
| 129 static void TearDown(); | |
| 130 // This method switches threads if we are running the Threading test. | |
| 131 // Otherwise it does nothing. | |
| 132 static void Fuzz(); | |
| 133 private: | |
| 134 static bool fuzzing_; | |
| 135 static int tests_being_run_; | |
| 136 static int current_; | |
| 137 static int active_tests_; | |
| 138 static bool NextThread(); | |
| 139 int test_number_; | |
| 140 v8::internal::Semaphore* gate_; | |
| 141 bool active_; | |
| 142 void ContextSwitch(); | |
| 143 static int GetNextTestNumber(); | |
| 144 static v8::internal::Semaphore* all_tests_done_; | |
| 145 }; | |
| 146 | |
| 147 | |
| 148 #define THREADED_TEST(Name) \ | |
| 149 static void Test##Name(); \ | |
| 150 RegisterThreadedTest register_##Name(Test##Name); \ | |
| 151 /* */ TEST(Name) | |
| 152 | |
| 153 | |
| 154 class RegisterThreadedTest { | |
| 155 public: | |
| 156 explicit RegisterThreadedTest(CcTest::TestFunction* callback) | |
| 157 : fuzzer_(NULL), callback_(callback) { | |
| 158 prev_ = first_; | |
| 159 first_ = this; | |
| 160 count_++; | |
| 161 } | |
| 162 static int count() { return count_; } | |
| 163 static RegisterThreadedTest* nth(int i) { | |
| 164 CHECK(i < count()); | |
| 165 RegisterThreadedTest* current = first_; | |
| 166 while (i > 0) { | |
| 167 i--; | |
| 168 current = current->prev_; | |
| 169 } | |
| 170 return current; | |
| 171 } | |
| 172 CcTest::TestFunction* callback() { return callback_; } | |
| 173 ApiTestFuzzer* fuzzer_; | |
| 174 | |
| 175 private: | |
| 176 static RegisterThreadedTest* first_; | |
| 177 static int count_; | |
| 178 CcTest::TestFunction* callback_; | |
| 179 RegisterThreadedTest* prev_; | |
| 180 }; | |
| 181 | |
| 182 | |
| 183 RegisterThreadedTest *RegisterThreadedTest::first_ = NULL; | |
| 184 int RegisterThreadedTest::count_ = 0; | |
| 185 | |
| 186 | 63 |
| 187 static int signature_callback_count; | 64 static int signature_callback_count; |
| 188 static v8::Handle<Value> IncrementingSignatureCallback( | 65 static v8::Handle<Value> IncrementingSignatureCallback( |
| 189 const v8::Arguments& args) { | 66 const v8::Arguments& args) { |
| 190 ApiTestFuzzer::Fuzz(); | 67 ApiTestFuzzer::Fuzz(); |
| 191 signature_callback_count++; | 68 signature_callback_count++; |
| 192 v8::Handle<v8::Array> result = v8::Array::New(args.Length()); | 69 v8::Handle<v8::Array> result = v8::Array::New(args.Length()); |
| 193 for (int i = 0; i < args.Length(); i++) | 70 for (int i = 0; i < args.Length(); i++) |
| 194 result->Set(v8::Integer::New(i), args[i]); | 71 result->Set(v8::Integer::New(i), args[i]); |
| 195 return result; | 72 return result; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 224 | 101 |
| 225 const char* c_source = "1 + 2 + 3"; | 102 const char* c_source = "1 + 2 + 3"; |
| 226 Local<String> source = String::New(c_source); | 103 Local<String> source = String::New(c_source); |
| 227 Local<Script> script = Script::Compile(source); | 104 Local<Script> script = Script::Compile(source); |
| 228 CHECK_EQ(6, script->Run()->Int32Value()); | 105 CHECK_EQ(6, script->Run()->Int32Value()); |
| 229 | 106 |
| 230 local_env->Exit(); | 107 local_env->Exit(); |
| 231 } | 108 } |
| 232 | 109 |
| 233 | 110 |
| 234 // Helper function that compiles and runs the source. | |
| 235 static Local<Value> CompileRun(const char* source) { | |
| 236 return Script::Compile(String::New(source))->Run(); | |
| 237 } | |
| 238 | |
| 239 THREADED_TEST(ReceiverSignature) { | 111 THREADED_TEST(ReceiverSignature) { |
| 240 v8::HandleScope scope; | 112 v8::HandleScope scope; |
| 241 LocalContext env; | 113 LocalContext env; |
| 242 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(); | 114 v8::Handle<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(); |
| 243 v8::Handle<v8::Signature> sig = v8::Signature::New(fun); | 115 v8::Handle<v8::Signature> sig = v8::Signature::New(fun); |
| 244 fun->PrototypeTemplate()->Set( | 116 fun->PrototypeTemplate()->Set( |
| 245 v8_str("m"), | 117 v8_str("m"), |
| 246 v8::FunctionTemplate::New(IncrementingSignatureCallback, | 118 v8::FunctionTemplate::New(IncrementingSignatureCallback, |
| 247 v8::Handle<Value>(), | 119 v8::Handle<Value>(), |
| 248 sig)); | 120 sig)); |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 // other_instance. | 585 // other_instance. |
| 714 CHECK_EQ(derived_instance2, | 586 CHECK_EQ(derived_instance2, |
| 715 other_instance->FindInstanceInPrototypeChain(base)); | 587 other_instance->FindInstanceInPrototypeChain(base)); |
| 716 CHECK_EQ(derived_instance2, | 588 CHECK_EQ(derived_instance2, |
| 717 other_instance->FindInstanceInPrototypeChain(derived)); | 589 other_instance->FindInstanceInPrototypeChain(derived)); |
| 718 CHECK_EQ(other_instance, | 590 CHECK_EQ(other_instance, |
| 719 other_instance->FindInstanceInPrototypeChain(other)); | 591 other_instance->FindInstanceInPrototypeChain(other)); |
| 720 } | 592 } |
| 721 | 593 |
| 722 | 594 |
| 723 static v8::Handle<Value> handle_property(Local<String> name, | |
| 724 const AccessorInfo&) { | |
| 725 ApiTestFuzzer::Fuzz(); | |
| 726 return v8_num(900); | |
| 727 } | |
| 728 | |
| 729 | |
| 730 THREADED_TEST(PropertyHandler) { | |
| 731 v8::HandleScope scope; | |
| 732 Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); | |
| 733 fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property); | |
| 734 LocalContext env; | |
| 735 Local<Function> fun = fun_templ->GetFunction(); | |
| 736 env->Global()->Set(v8_str("Fun"), fun); | |
| 737 Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;"); | |
| 738 CHECK_EQ(900, getter->Run()->Int32Value()); | |
| 739 Local<Script> setter = v8_compile("obj.foo = 901;"); | |
| 740 CHECK_EQ(901, setter->Run()->Int32Value()); | |
| 741 } | |
| 742 | |
| 743 | |
| 744 THREADED_TEST(TinyInteger) { | 595 THREADED_TEST(TinyInteger) { |
| 745 v8::HandleScope scope; | 596 v8::HandleScope scope; |
| 746 LocalContext env; | 597 LocalContext env; |
| 747 int32_t value = 239; | 598 int32_t value = 239; |
| 748 Local<v8::Integer> value_obj = v8::Integer::New(value); | 599 Local<v8::Integer> value_obj = v8::Integer::New(value); |
| 749 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); | 600 CHECK_EQ(static_cast<int64_t>(value), value_obj->Value()); |
| 750 } | 601 } |
| 751 | 602 |
| 752 | 603 |
| 753 THREADED_TEST(BigSmiInteger) { | 604 THREADED_TEST(BigSmiInteger) { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 900 LocalContext env(0, templ); | 751 LocalContext env(0, templ); |
| 901 v8::Handle<v8::Object> obj = env->Global(); | 752 v8::Handle<v8::Object> obj = env->Global(); |
| 902 v8::Handle<Script> script = v8_compile("dummy()"); | 753 v8::Handle<Script> script = v8_compile("dummy()"); |
| 903 v8::Handle<Value> result = script->Run(); | 754 v8::Handle<Value> result = script->Run(); |
| 904 CHECK_EQ(13.4, result->NumberValue()); | 755 CHECK_EQ(13.4, result->NumberValue()); |
| 905 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value()); | 756 CHECK_EQ(200, v8_compile("x")->Run()->Int32Value()); |
| 906 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value()); | 757 CHECK_EQ(876, v8_compile("m")->Run()->Int32Value()); |
| 907 } | 758 } |
| 908 | 759 |
| 909 | 760 |
| 910 static v8::Handle<Value> GetIntValue(Local<String> property, | |
| 911 const AccessorInfo& info) { | |
| 912 ApiTestFuzzer::Fuzz(); | |
| 913 int* value = | |
| 914 static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); | |
| 915 return v8_num(*value); | |
| 916 } | |
| 917 | |
| 918 static void SetIntValue(Local<String> property, | |
| 919 Local<Value> value, | |
| 920 const AccessorInfo& info) { | |
| 921 int* field = | |
| 922 static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); | |
| 923 *field = value->Int32Value(); | |
| 924 } | |
| 925 | |
| 926 int foo, bar, baz; | |
| 927 | |
| 928 THREADED_TEST(GlobalVariableAccess) { | |
| 929 foo = 0; | |
| 930 bar = -4; | |
| 931 baz = 10; | |
| 932 v8::HandleScope scope; | |
| 933 v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(); | |
| 934 templ->InstanceTemplate()->SetAccessor(v8_str("foo"), | |
| 935 GetIntValue, | |
| 936 SetIntValue, | |
| 937 v8::External::New(&foo)); | |
| 938 templ->InstanceTemplate()->SetAccessor(v8_str("bar"), | |
| 939 GetIntValue, | |
| 940 SetIntValue, | |
| 941 v8::External::New(&bar)); | |
| 942 templ->InstanceTemplate()->SetAccessor(v8_str("baz"), | |
| 943 GetIntValue, | |
| 944 SetIntValue, | |
| 945 v8::External::New(&baz)); | |
| 946 LocalContext env(0, templ->InstanceTemplate()); | |
| 947 v8_compile("foo = (++bar) + baz")->Run(); | |
| 948 CHECK_EQ(bar, -3); | |
| 949 CHECK_EQ(foo, 7); | |
| 950 } | |
| 951 | |
| 952 | |
| 953 THREADED_TEST(ObjectTemplate) { | 761 THREADED_TEST(ObjectTemplate) { |
| 954 v8::HandleScope scope; | 762 v8::HandleScope scope; |
| 955 Local<ObjectTemplate> templ1 = ObjectTemplate::New(); | 763 Local<ObjectTemplate> templ1 = ObjectTemplate::New(); |
| 956 templ1->Set("x", v8_num(10)); | 764 templ1->Set("x", v8_num(10)); |
| 957 templ1->Set("y", v8_num(13)); | 765 templ1->Set("y", v8_num(13)); |
| 958 LocalContext env; | 766 LocalContext env; |
| 959 Local<v8::Object> instance1 = templ1->NewInstance(); | 767 Local<v8::Object> instance1 = templ1->NewInstance(); |
| 960 env->Global()->Set(v8_str("p"), instance1); | 768 env->Global()->Set(v8_str("p"), instance1); |
| 961 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue()); | 769 CHECK(v8_compile("(p.x == 10)")->Run()->BooleanValue()); |
| 962 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue()); | 770 CHECK(v8_compile("(p.y == 13)")->Run()->BooleanValue()); |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 env->Global()->Set(v8_str("obj"), obj->NewInstance()); | 1166 env->Global()->Set(v8_str("obj"), obj->NewInstance()); |
| 1359 v8::Handle<Value> otto = Script::Compile(v8_str( | 1167 v8::Handle<Value> otto = Script::Compile(v8_str( |
| 1360 "try { with (obj) { otto; } } catch (e) { e; }"))->Run(); | 1168 "try { with (obj) { otto; } } catch (e) { e; }"))->Run(); |
| 1361 CHECK_EQ(v8_str("otto"), otto); | 1169 CHECK_EQ(v8_str("otto"), otto); |
| 1362 v8::Handle<Value> netto = Script::Compile(v8_str( | 1170 v8::Handle<Value> netto = Script::Compile(v8_str( |
| 1363 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run(); | 1171 "try { with (obj) { netto = 4; } } catch (e) { e; }"))->Run(); |
| 1364 CHECK_EQ(v8_str("netto"), netto); | 1172 CHECK_EQ(v8_str("netto"), netto); |
| 1365 } | 1173 } |
| 1366 | 1174 |
| 1367 | 1175 |
| 1368 static v8::Handle<Value> ThrowingGetAccessor(Local<String> name, | |
| 1369 const AccessorInfo& info) { | |
| 1370 ApiTestFuzzer::Fuzz(); | |
| 1371 return v8::ThrowException(v8_str("g")); | |
| 1372 } | |
| 1373 | |
| 1374 | |
| 1375 static void ThrowingSetAccessor(Local<String> name, | |
| 1376 Local<Value> value, | |
| 1377 const AccessorInfo& info) { | |
| 1378 v8::ThrowException(value); | |
| 1379 } | |
| 1380 | |
| 1381 | |
| 1382 THREADED_TEST(Regress1054726) { | |
| 1383 v8::HandleScope scope; | |
| 1384 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(); | |
| 1385 obj->SetAccessor(v8_str("x"), | |
| 1386 ThrowingGetAccessor, | |
| 1387 ThrowingSetAccessor, | |
| 1388 Local<Value>()); | |
| 1389 | |
| 1390 LocalContext env; | |
| 1391 env->Global()->Set(v8_str("obj"), obj->NewInstance()); | |
| 1392 | |
| 1393 // Use the throwing property setter/getter in a loop to force | |
| 1394 // the accessor ICs to be initialized. | |
| 1395 v8::Handle<Value> result; | |
| 1396 result = Script::Compile(v8_str( | |
| 1397 "var result = '';" | |
| 1398 "for (var i = 0; i < 5; i++) {" | |
| 1399 " try { obj.x; } catch (e) { result += e; }" | |
| 1400 "}; result"))->Run(); | |
| 1401 CHECK_EQ(v8_str("ggggg"), result); | |
| 1402 | |
| 1403 result = Script::Compile(String::New( | |
| 1404 "var result = '';" | |
| 1405 "for (var i = 0; i < 5; i++) {" | |
| 1406 " try { obj.x = i; } catch (e) { result += e; }" | |
| 1407 "}; result"))->Run(); | |
| 1408 CHECK_EQ(v8_str("01234"), result); | |
| 1409 } | |
| 1410 | |
| 1411 | |
| 1412 THREADED_TEST(FunctionPrototype) { | 1176 THREADED_TEST(FunctionPrototype) { |
| 1413 v8::HandleScope scope; | 1177 v8::HandleScope scope; |
| 1414 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(); | 1178 Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New(); |
| 1415 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321)); | 1179 Foo->PrototypeTemplate()->Set(v8_str("plak"), v8_num(321)); |
| 1416 LocalContext env; | 1180 LocalContext env; |
| 1417 env->Global()->Set(v8_str("Foo"), Foo->GetFunction()); | 1181 env->Global()->Set(v8_str("Foo"), Foo->GetFunction()); |
| 1418 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak")); | 1182 Local<Script> script = Script::Compile(v8_str("Foo.prototype.plak")); |
| 1419 CHECK_EQ(script->Run()->Int32Value(), 321); | 1183 CHECK_EQ(script->Run()->Int32Value(), 321); |
| 1420 } | 1184 } |
| 1421 | 1185 |
| (...skipping 1807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3229 THREADED_TEST(Arguments) { | 2993 THREADED_TEST(Arguments) { |
| 3230 v8::HandleScope scope; | 2994 v8::HandleScope scope; |
| 3231 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(); | 2995 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(); |
| 3232 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback)); | 2996 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback)); |
| 3233 LocalContext context(NULL, global); | 2997 LocalContext context(NULL, global); |
| 3234 args_fun = v8::Handle<Function>::Cast(context->Global()->Get(v8_str("f"))); | 2998 args_fun = v8::Handle<Function>::Cast(context->Global()->Get(v8_str("f"))); |
| 3235 v8_compile("f(1, 2, 3)")->Run(); | 2999 v8_compile("f(1, 2, 3)")->Run(); |
| 3236 } | 3000 } |
| 3237 | 3001 |
| 3238 | 3002 |
| 3239 static int x_register = 0; | |
| 3240 static v8::Handle<v8::Object> x_receiver; | |
| 3241 static v8::Handle<v8::Object> x_holder; | |
| 3242 | |
| 3243 | |
| 3244 static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) { | |
| 3245 ApiTestFuzzer::Fuzz(); | |
| 3246 CHECK_EQ(x_receiver, info.This()); | |
| 3247 CHECK_EQ(x_holder, info.Holder()); | |
| 3248 return v8_num(x_register); | |
| 3249 } | |
| 3250 | |
| 3251 | |
| 3252 static void XSetter(Local<String> name, | |
| 3253 Local<Value> value, | |
| 3254 const AccessorInfo& info) { | |
| 3255 CHECK_EQ(x_holder, info.This()); | |
| 3256 CHECK_EQ(x_holder, info.Holder()); | |
| 3257 x_register = value->Int32Value(); | |
| 3258 } | |
| 3259 | |
| 3260 | |
| 3261 THREADED_TEST(AccessorIC) { | |
| 3262 v8::HandleScope scope; | |
| 3263 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(); | |
| 3264 obj->SetAccessor(v8_str("x"), XGetter, XSetter); | |
| 3265 LocalContext context; | |
| 3266 x_holder = obj->NewInstance(); | |
| 3267 context->Global()->Set(v8_str("holder"), x_holder); | |
| 3268 x_receiver = v8::Object::New(); | |
| 3269 context->Global()->Set(v8_str("obj"), x_receiver); | |
| 3270 v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun( | |
| 3271 "obj.__proto__ = holder;" | |
| 3272 "var result = [];" | |
| 3273 "for (var i = 0; i < 10; i++) {" | |
| 3274 " holder.x = i;" | |
| 3275 " result.push(obj.x);" | |
| 3276 "}" | |
| 3277 "result")); | |
| 3278 CHECK_EQ(10, array->Length()); | |
| 3279 for (int i = 0; i < 10; i++) { | |
| 3280 v8::Handle<Value> entry = array->Get(v8::Integer::New(i)); | |
| 3281 CHECK_EQ(v8::Integer::New(i), entry); | |
| 3282 } | |
| 3283 } | |
| 3284 | |
| 3285 | |
| 3286 static v8::Handle<Value> NoBlockGetterX(Local<String> name, | 3003 static v8::Handle<Value> NoBlockGetterX(Local<String> name, |
| 3287 const AccessorInfo&) { | 3004 const AccessorInfo&) { |
| 3288 return v8::Handle<Value>(); | 3005 return v8::Handle<Value>(); |
| 3289 } | 3006 } |
| 3290 | 3007 |
| 3291 | 3008 |
| 3292 static v8::Handle<Value> NoBlockGetterI(uint32_t index, | 3009 static v8::Handle<Value> NoBlockGetterI(uint32_t index, |
| 3293 const AccessorInfo&) { | 3010 const AccessorInfo&) { |
| 3294 return v8::Handle<Value>(); | 3011 return v8::Handle<Value>(); |
| 3295 } | 3012 } |
| (...skipping 2843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6139 if (!fuzzing_) return; | 5856 if (!fuzzing_) return; |
| 6140 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_; | 5857 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_; |
| 6141 test->ContextSwitch(); | 5858 test->ContextSwitch(); |
| 6142 } | 5859 } |
| 6143 | 5860 |
| 6144 | 5861 |
| 6145 // Let the next thread go. Since it is also waiting on the V8 lock it may | 5862 // Let the next thread go. Since it is also waiting on the V8 lock it may |
| 6146 // not start immediately. | 5863 // not start immediately. |
| 6147 bool ApiTestFuzzer::NextThread() { | 5864 bool ApiTestFuzzer::NextThread() { |
| 6148 int test_position = GetNextTestNumber(); | 5865 int test_position = GetNextTestNumber(); |
| 6149 int test_number = RegisterThreadedTest::nth(current_)->fuzzer_->test_number_; | 5866 const char* test_name = RegisterThreadedTest::nth(current_)->name(); |
| 6150 if (test_position == current_) { | 5867 if (test_position == current_) { |
| 6151 printf("Stay with %d\n", test_number); | 5868 if (kLogThreading) |
| 5869 printf("Stay with %s\n", test_name); |
| 6152 return false; | 5870 return false; |
| 6153 } | 5871 } |
| 6154 printf("Switch from %d to %d\n", | 5872 if (kLogThreading) { |
| 6155 current_ < 0 ? 0 : test_number, test_position < 0 ? 0 : test_number); | 5873 printf("Switch from %s to %s\n", |
| 5874 test_name, |
| 5875 RegisterThreadedTest::nth(test_position)->name()); |
| 5876 } |
| 6156 current_ = test_position; | 5877 current_ = test_position; |
| 6157 RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal(); | 5878 RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal(); |
| 6158 return true; | 5879 return true; |
| 6159 } | 5880 } |
| 6160 | 5881 |
| 6161 | 5882 |
| 6162 void ApiTestFuzzer::Run() { | 5883 void ApiTestFuzzer::Run() { |
| 6163 // When it is our turn... | 5884 // When it is our turn... |
| 6164 gate_->Wait(); | 5885 gate_->Wait(); |
| 6165 { | 5886 { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6254 } | 5975 } |
| 6255 | 5976 |
| 6256 TEST(Threading2) { | 5977 TEST(Threading2) { |
| 6257 ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART); | 5978 ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART); |
| 6258 ApiTestFuzzer::RunAllTests(); | 5979 ApiTestFuzzer::RunAllTests(); |
| 6259 ApiTestFuzzer::TearDown(); | 5980 ApiTestFuzzer::TearDown(); |
| 6260 } | 5981 } |
| 6261 | 5982 |
| 6262 | 5983 |
| 6263 void ApiTestFuzzer::CallTest() { | 5984 void ApiTestFuzzer::CallTest() { |
| 6264 printf("Start test %d\n", test_number_); | 5985 if (kLogThreading) |
| 5986 printf("Start test %d\n", test_number_); |
| 6265 CallTestNumber(test_number_); | 5987 CallTestNumber(test_number_); |
| 6266 printf("End test %d\n", test_number_); | 5988 if (kLogThreading) |
| 5989 printf("End test %d\n", test_number_); |
| 6267 } | 5990 } |
| 6268 | 5991 |
| 6269 | 5992 |
| 6270 static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) { | 5993 static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) { |
| 6271 CHECK(v8::Locker::IsLocked()); | 5994 CHECK(v8::Locker::IsLocked()); |
| 6272 ApiTestFuzzer::Fuzz(); | 5995 ApiTestFuzzer::Fuzz(); |
| 6273 v8::Unlocker unlocker; | 5996 v8::Unlocker unlocker; |
| 6274 const char* code = "throw 7;"; | 5997 const char* code = "throw 7;"; |
| 6275 { | 5998 { |
| 6276 v8::Locker nested_locker; | 5999 v8::Locker nested_locker; |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6744 CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1); | 6467 CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1); |
| 6745 int elmc2 = 3; | 6468 int elmc2 = 3; |
| 6746 const char* elmv2[] = {"0", "1", "2"}; | 6469 const char* elmv2[] = {"0", "1", "2"}; |
| 6747 CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2); | 6470 CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2); |
| 6748 int elmc3 = 4; | 6471 int elmc3 = 4; |
| 6749 const char* elmv3[] = {"w", "z", "x", "y"}; | 6472 const char* elmv3[] = {"w", "z", "x", "y"}; |
| 6750 CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3); | 6473 CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3); |
| 6751 } | 6474 } |
| 6752 | 6475 |
| 6753 | 6476 |
| 6754 static v8::Handle<Value> AccessorProhibitsOverwritingGetter( | |
| 6755 Local<String> name, | |
| 6756 const AccessorInfo& info) { | |
| 6757 ApiTestFuzzer::Fuzz(); | |
| 6758 return v8::True(); | |
| 6759 } | |
| 6760 | |
| 6761 | |
| 6762 THREADED_TEST(AccessorProhibitsOverwriting) { | |
| 6763 v8::HandleScope scope; | |
| 6764 LocalContext context; | |
| 6765 Local<ObjectTemplate> templ = ObjectTemplate::New(); | |
| 6766 templ->SetAccessor(v8_str("x"), | |
| 6767 AccessorProhibitsOverwritingGetter, | |
| 6768 0, | |
| 6769 v8::Handle<Value>(), | |
| 6770 v8::PROHIBITS_OVERWRITING, | |
| 6771 v8::ReadOnly); | |
| 6772 Local<v8::Object> instance = templ->NewInstance(); | |
| 6773 context->Global()->Set(v8_str("obj"), instance); | |
| 6774 Local<Value> value = CompileRun( | |
| 6775 "obj.__defineGetter__('x', function() { return false; });" | |
| 6776 "obj.x"); | |
| 6777 CHECK(value->BooleanValue()); | |
| 6778 value = CompileRun( | |
| 6779 "var setter_called = false;" | |
| 6780 "obj.__defineSetter__('x', function() { setter_called = true; });" | |
| 6781 "obj.x = 42;" | |
| 6782 "setter_called"); | |
| 6783 CHECK(!value->BooleanValue()); | |
| 6784 value = CompileRun( | |
| 6785 "obj2 = {};" | |
| 6786 "obj2.__proto__ = obj;" | |
| 6787 "obj2.__defineGetter__('x', function() { return false; });" | |
| 6788 "obj2.x"); | |
| 6789 CHECK(value->BooleanValue()); | |
| 6790 value = CompileRun( | |
| 6791 "var setter_called = false;" | |
| 6792 "obj2 = {};" | |
| 6793 "obj2.__proto__ = obj;" | |
| 6794 "obj2.__defineSetter__('x', function() { setter_called = true; });" | |
| 6795 "obj2.x = 42;" | |
| 6796 "setter_called"); | |
| 6797 CHECK(!value->BooleanValue()); | |
| 6798 } | |
| 6799 | |
| 6800 | |
| 6801 static bool NamedSetAccessBlocker(Local<v8::Object> obj, | 6477 static bool NamedSetAccessBlocker(Local<v8::Object> obj, |
| 6802 Local<Value> name, | 6478 Local<Value> name, |
| 6803 v8::AccessType type, | 6479 v8::AccessType type, |
| 6804 Local<Value> data) { | 6480 Local<Value> data) { |
| 6805 return type != v8::ACCESS_SET; | 6481 return type != v8::ACCESS_SET; |
| 6806 } | 6482 } |
| 6807 | 6483 |
| 6808 | 6484 |
| 6809 static bool IndexedSetAccessBlocker(Local<v8::Object> obj, | 6485 static bool IndexedSetAccessBlocker(Local<v8::Object> obj, |
| 6810 uint32_t key, | 6486 uint32_t key, |
| (...skipping 1882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8693 " i++;" | 8369 " i++;" |
| 8694 " return s(o);" | 8370 " return s(o);" |
| 8695 " }" | 8371 " }" |
| 8696 " }" | 8372 " }" |
| 8697 "};" | 8373 "};" |
| 8698 "s(o);"); | 8374 "s(o);"); |
| 8699 CHECK(try_catch.HasCaught()); | 8375 CHECK(try_catch.HasCaught()); |
| 8700 v8::String::Utf8Value value(try_catch.Exception()); | 8376 v8::String::Utf8Value value(try_catch.Exception()); |
| 8701 CHECK_EQ(0, strcmp(*value, "Hey!")); | 8377 CHECK_EQ(0, strcmp(*value, "Hey!")); |
| 8702 } | 8378 } |
| OLD | NEW |