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 1755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3177 THREADED_TEST(Arguments) { | 2941 THREADED_TEST(Arguments) { |
3178 v8::HandleScope scope; | 2942 v8::HandleScope scope; |
3179 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(); | 2943 v8::Handle<v8::ObjectTemplate> global = ObjectTemplate::New(); |
3180 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback)); | 2944 global->Set(v8_str("f"), v8::FunctionTemplate::New(ArgumentsTestCallback)); |
3181 LocalContext context(NULL, global); | 2945 LocalContext context(NULL, global); |
3182 args_fun = v8::Handle<Function>::Cast(context->Global()->Get(v8_str("f"))); | 2946 args_fun = v8::Handle<Function>::Cast(context->Global()->Get(v8_str("f"))); |
3183 v8_compile("f(1, 2, 3)")->Run(); | 2947 v8_compile("f(1, 2, 3)")->Run(); |
3184 } | 2948 } |
3185 | 2949 |
3186 | 2950 |
3187 static int x_register = 0; | |
3188 static v8::Handle<v8::Object> x_receiver; | |
3189 static v8::Handle<v8::Object> x_holder; | |
3190 | |
3191 | |
3192 static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) { | |
3193 ApiTestFuzzer::Fuzz(); | |
3194 CHECK_EQ(x_receiver, info.This()); | |
3195 CHECK_EQ(x_holder, info.Holder()); | |
3196 return v8_num(x_register); | |
3197 } | |
3198 | |
3199 | |
3200 static void XSetter(Local<String> name, | |
3201 Local<Value> value, | |
3202 const AccessorInfo& info) { | |
3203 CHECK_EQ(x_holder, info.This()); | |
3204 CHECK_EQ(x_holder, info.Holder()); | |
3205 x_register = value->Int32Value(); | |
3206 } | |
3207 | |
3208 | |
3209 THREADED_TEST(AccessorIC) { | |
3210 v8::HandleScope scope; | |
3211 v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New(); | |
3212 obj->SetAccessor(v8_str("x"), XGetter, XSetter); | |
3213 LocalContext context; | |
3214 x_holder = obj->NewInstance(); | |
3215 context->Global()->Set(v8_str("holder"), x_holder); | |
3216 x_receiver = v8::Object::New(); | |
3217 context->Global()->Set(v8_str("obj"), x_receiver); | |
3218 v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun( | |
3219 "obj.__proto__ = holder;" | |
3220 "var result = [];" | |
3221 "for (var i = 0; i < 10; i++) {" | |
3222 " holder.x = i;" | |
3223 " result.push(obj.x);" | |
3224 "}" | |
3225 "result")); | |
3226 CHECK_EQ(10, array->Length()); | |
3227 for (int i = 0; i < 10; i++) { | |
3228 v8::Handle<Value> entry = array->Get(v8::Integer::New(i)); | |
3229 CHECK_EQ(v8::Integer::New(i), entry); | |
3230 } | |
3231 } | |
3232 | |
3233 | |
3234 static v8::Handle<Value> NoBlockGetterX(Local<String> name, | 2951 static v8::Handle<Value> NoBlockGetterX(Local<String> name, |
3235 const AccessorInfo&) { | 2952 const AccessorInfo&) { |
3236 return v8::Handle<Value>(); | 2953 return v8::Handle<Value>(); |
3237 } | 2954 } |
3238 | 2955 |
3239 | 2956 |
3240 static v8::Handle<Value> NoBlockGetterI(uint32_t index, | 2957 static v8::Handle<Value> NoBlockGetterI(uint32_t index, |
3241 const AccessorInfo&) { | 2958 const AccessorInfo&) { |
3242 return v8::Handle<Value>(); | 2959 return v8::Handle<Value>(); |
3243 } | 2960 } |
(...skipping 2843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6087 if (!fuzzing_) return; | 5804 if (!fuzzing_) return; |
6088 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_; | 5805 ApiTestFuzzer* test = RegisterThreadedTest::nth(current_)->fuzzer_; |
6089 test->ContextSwitch(); | 5806 test->ContextSwitch(); |
6090 } | 5807 } |
6091 | 5808 |
6092 | 5809 |
6093 // Let the next thread go. Since it is also waiting on the V8 lock it may | 5810 // Let the next thread go. Since it is also waiting on the V8 lock it may |
6094 // not start immediately. | 5811 // not start immediately. |
6095 bool ApiTestFuzzer::NextThread() { | 5812 bool ApiTestFuzzer::NextThread() { |
6096 int test_position = GetNextTestNumber(); | 5813 int test_position = GetNextTestNumber(); |
6097 int test_number = RegisterThreadedTest::nth(current_)->fuzzer_->test_number_; | 5814 const char* test_name = RegisterThreadedTest::nth(current_)->name(); |
6098 if (test_position == current_) { | 5815 if (test_position == current_) { |
6099 printf("Stay with %d\n", test_number); | 5816 if (kLogThreading) |
| 5817 printf("Stay with %s\n", test_name); |
6100 return false; | 5818 return false; |
6101 } | 5819 } |
6102 printf("Switch from %d to %d\n", | 5820 if (kLogThreading) { |
6103 current_ < 0 ? 0 : test_number, test_position < 0 ? 0 : test_number); | 5821 printf("Switch from %s to %s\n", |
| 5822 test_name, |
| 5823 RegisterThreadedTest::nth(test_position)->name()); |
| 5824 } |
6104 current_ = test_position; | 5825 current_ = test_position; |
6105 RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal(); | 5826 RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal(); |
6106 return true; | 5827 return true; |
6107 } | 5828 } |
6108 | 5829 |
6109 | 5830 |
6110 void ApiTestFuzzer::Run() { | 5831 void ApiTestFuzzer::Run() { |
6111 // When it is our turn... | 5832 // When it is our turn... |
6112 gate_->Wait(); | 5833 gate_->Wait(); |
6113 { | 5834 { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6202 } | 5923 } |
6203 | 5924 |
6204 TEST(Threading2) { | 5925 TEST(Threading2) { |
6205 ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART); | 5926 ApiTestFuzzer::Setup(ApiTestFuzzer::SECOND_PART); |
6206 ApiTestFuzzer::RunAllTests(); | 5927 ApiTestFuzzer::RunAllTests(); |
6207 ApiTestFuzzer::TearDown(); | 5928 ApiTestFuzzer::TearDown(); |
6208 } | 5929 } |
6209 | 5930 |
6210 | 5931 |
6211 void ApiTestFuzzer::CallTest() { | 5932 void ApiTestFuzzer::CallTest() { |
6212 printf("Start test %d\n", test_number_); | 5933 if (kLogThreading) |
| 5934 printf("Start test %d\n", test_number_); |
6213 CallTestNumber(test_number_); | 5935 CallTestNumber(test_number_); |
6214 printf("End test %d\n", test_number_); | 5936 if (kLogThreading) |
| 5937 printf("End test %d\n", test_number_); |
6215 } | 5938 } |
6216 | 5939 |
6217 | 5940 |
6218 static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) { | 5941 static v8::Handle<Value> ThrowInJS(const v8::Arguments& args) { |
6219 CHECK(v8::Locker::IsLocked()); | 5942 CHECK(v8::Locker::IsLocked()); |
6220 ApiTestFuzzer::Fuzz(); | 5943 ApiTestFuzzer::Fuzz(); |
6221 v8::Unlocker unlocker; | 5944 v8::Unlocker unlocker; |
6222 const char* code = "throw 7;"; | 5945 const char* code = "throw 7;"; |
6223 { | 5946 { |
6224 v8::Locker nested_locker; | 5947 v8::Locker nested_locker; |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6692 CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1); | 6415 CheckProperties(elms->Get(v8::Integer::New(1)), elmc1, elmv1); |
6693 int elmc2 = 3; | 6416 int elmc2 = 3; |
6694 const char* elmv2[] = {"0", "1", "2"}; | 6417 const char* elmv2[] = {"0", "1", "2"}; |
6695 CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2); | 6418 CheckProperties(elms->Get(v8::Integer::New(2)), elmc2, elmv2); |
6696 int elmc3 = 4; | 6419 int elmc3 = 4; |
6697 const char* elmv3[] = {"w", "z", "x", "y"}; | 6420 const char* elmv3[] = {"w", "z", "x", "y"}; |
6698 CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3); | 6421 CheckProperties(elms->Get(v8::Integer::New(3)), elmc3, elmv3); |
6699 } | 6422 } |
6700 | 6423 |
6701 | 6424 |
6702 static v8::Handle<Value> AccessorProhibitsOverwritingGetter( | |
6703 Local<String> name, | |
6704 const AccessorInfo& info) { | |
6705 ApiTestFuzzer::Fuzz(); | |
6706 return v8::True(); | |
6707 } | |
6708 | |
6709 | |
6710 THREADED_TEST(AccessorProhibitsOverwriting) { | |
6711 v8::HandleScope scope; | |
6712 LocalContext context; | |
6713 Local<ObjectTemplate> templ = ObjectTemplate::New(); | |
6714 templ->SetAccessor(v8_str("x"), | |
6715 AccessorProhibitsOverwritingGetter, | |
6716 0, | |
6717 v8::Handle<Value>(), | |
6718 v8::PROHIBITS_OVERWRITING, | |
6719 v8::ReadOnly); | |
6720 Local<v8::Object> instance = templ->NewInstance(); | |
6721 context->Global()->Set(v8_str("obj"), instance); | |
6722 Local<Value> value = CompileRun( | |
6723 "obj.__defineGetter__('x', function() { return false; });" | |
6724 "obj.x"); | |
6725 CHECK(value->BooleanValue()); | |
6726 value = CompileRun( | |
6727 "var setter_called = false;" | |
6728 "obj.__defineSetter__('x', function() { setter_called = true; });" | |
6729 "obj.x = 42;" | |
6730 "setter_called"); | |
6731 CHECK(!value->BooleanValue()); | |
6732 value = CompileRun( | |
6733 "obj2 = {};" | |
6734 "obj2.__proto__ = obj;" | |
6735 "obj2.__defineGetter__('x', function() { return false; });" | |
6736 "obj2.x"); | |
6737 CHECK(value->BooleanValue()); | |
6738 value = CompileRun( | |
6739 "var setter_called = false;" | |
6740 "obj2 = {};" | |
6741 "obj2.__proto__ = obj;" | |
6742 "obj2.__defineSetter__('x', function() { setter_called = true; });" | |
6743 "obj2.x = 42;" | |
6744 "setter_called"); | |
6745 CHECK(!value->BooleanValue()); | |
6746 } | |
6747 | |
6748 | |
6749 static bool NamedSetAccessBlocker(Local<v8::Object> obj, | 6425 static bool NamedSetAccessBlocker(Local<v8::Object> obj, |
6750 Local<Value> name, | 6426 Local<Value> name, |
6751 v8::AccessType type, | 6427 v8::AccessType type, |
6752 Local<Value> data) { | 6428 Local<Value> data) { |
6753 return type != v8::ACCESS_SET; | 6429 return type != v8::ACCESS_SET; |
6754 } | 6430 } |
6755 | 6431 |
6756 | 6432 |
6757 static bool IndexedSetAccessBlocker(Local<v8::Object> obj, | 6433 static bool IndexedSetAccessBlocker(Local<v8::Object> obj, |
6758 uint32_t key, | 6434 uint32_t key, |
(...skipping 1844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8603 double stored_date = date->NumberValue(); | 8279 double stored_date = date->NumberValue(); |
8604 if (!IsNaN(expected_stored_date)) { | 8280 if (!IsNaN(expected_stored_date)) { |
8605 CHECK_EQ(expected_stored_date, stored_date); | 8281 CHECK_EQ(expected_stored_date, stored_date); |
8606 } else { | 8282 } else { |
8607 uint64_t stored_bits = DoubleToBits(stored_date); | 8283 uint64_t stored_bits = DoubleToBits(stored_date); |
8608 // Check if quiet nan (bits 51..62 all set). | 8284 // Check if quiet nan (bits 51..62 all set). |
8609 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff)); | 8285 CHECK_EQ(0xfff, static_cast<int>((stored_bits >> 51) & 0xfff)); |
8610 } | 8286 } |
8611 } | 8287 } |
8612 } | 8288 } |
OLD | NEW |