Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 #include <vector> | 1 #include <vector> |
2 #include <stdexcept> | |
2 | 3 |
3 #include "GlobalJsObject.h" | 4 #include "GlobalJsObject.h" |
4 #include "Thread.h" | 5 #include "Thread.h" |
5 | 6 |
6 using namespace AdblockPlus; | 7 using namespace AdblockPlus; |
7 | 8 |
8 namespace | 9 namespace |
9 { | 10 { |
10 class TimeoutThread : public Thread | 11 class TimeoutThread : public Thread |
11 { | 12 { |
12 public: | 13 public: |
13 TimeoutThread(v8::Isolate* const isolate, const v8::Arguments& arguments) | 14 TimeoutThread(v8::Isolate* const isolate, const v8::Arguments& arguments) |
14 : isolate(isolate) | 15 : isolate(isolate) |
15 { | 16 { |
17 if (arguments.Length() < 2) | |
18 throw std::runtime_error("setTimeout requires at least 2 parameters"); | |
19 | |
20 const v8::Local<v8::Value> functionValue = arguments[0]; | |
21 if (!functionValue->IsFunction()) | |
22 throw std::runtime_error("No valid function passed to setTimeout"); | |
Wladimir Palant
2013/04/08 14:03:47
Nit: I think the canonical message is: "First argu
| |
23 | |
24 const v8::Local<v8::Value> delayValue = arguments[1]; | |
25 if (!delayValue->IsNumber()) | |
26 throw std::runtime_error("No valid delay passed to setTimeout"); | |
Wladimir Palant
2013/04/08 14:03:47
Nit: I think the canonical message is: "Second arg
| |
27 | |
16 function = v8::Persistent<v8::Function>::New( | 28 function = v8::Persistent<v8::Function>::New( |
17 isolate, v8::Local<v8::Function>::Cast(arguments[0])); | 29 isolate, v8::Local<v8::Function>::Cast(functionValue)); |
Felix Dahlke
2013/04/08 13:07:49
Phew, good find. V8 isn't exactly documented but I
| |
18 delay = arguments[1]->ToNumber()->Value(); | 30 delay = delayValue->ToNumber()->Value(); |
19 for (int i = 2; i < arguments.Length(); i++) | 31 for (int i = 2; i < arguments.Length(); i++) |
20 { | 32 { |
21 const Value argument = Value::New(isolate, arguments[i]); | 33 const Value argument = Value::New(isolate, arguments[i]); |
22 functionArguments.push_back(argument); | 34 functionArguments.push_back(argument); |
23 } | 35 } |
24 } | 36 } |
25 | 37 |
26 ~TimeoutThread() | 38 ~TimeoutThread() |
27 { | 39 { |
28 function.Dispose(isolate); | 40 function.Dispose(isolate); |
29 for (Values::iterator it = functionArguments.begin(); | 41 for (Values::iterator it = functionArguments.begin(); |
30 it != functionArguments.end(); it++) | 42 it != functionArguments.end(); it++) |
31 it->Dispose(isolate); | 43 it->Dispose(isolate); |
32 } | 44 } |
33 | 45 |
34 void Run() | 46 void Run() |
35 { | 47 { |
36 Sleep(delay); | 48 Sleep(delay); |
37 const v8::Locker locker(isolate); | 49 const v8::Locker locker(isolate); |
Wladimir Palant
2013/04/08 08:36:00
Does this really lock when this line is reached or
| |
38 const v8::HandleScope handleScope; | 50 const v8::HandleScope handleScope; |
39 function->Call(function, functionArguments.size(), &functionArguments[0]); | 51 function->Call(function, functionArguments.size(), &functionArguments[0]); |
40 delete this; | 52 delete this; |
Wladimir Palant
2013/04/08 08:36:00
Self-deleting object?
1) Is that a good practice?
Felix Dahlke
2013/04/08 13:07:49
1) Depends. It's not generally considered a bad pr
Wladimir Palant
2013/04/08 14:03:47
I checked, delete is actually thread-safe - so no
| |
41 } | 53 } |
42 | 54 |
43 private: | 55 private: |
44 typedef v8::Persistent<v8::Value> Value; | 56 typedef v8::Persistent<v8::Value> Value; |
45 typedef std::vector<Value> Values; | 57 typedef std::vector<Value> Values; |
46 | 58 |
47 v8::Isolate* const isolate; | 59 v8::Isolate* const isolate; |
48 v8::Persistent<v8::Function> function; | 60 v8::Persistent<v8::Function> function; |
49 int delay; | 61 int delay; |
50 Values functionArguments; | 62 Values functionArguments; |
51 }; | 63 }; |
52 | 64 |
53 v8::Handle<v8::Value> SetTimeoutCallback(const v8::Arguments& arguments) | 65 v8::Handle<v8::Value> SetTimeoutCallback(const v8::Arguments& arguments) |
54 { | 66 { |
55 TimeoutThread* const timeoutThread = | 67 TimeoutThread* timeoutThread; |
56 new TimeoutThread(v8::Isolate::GetCurrent(), arguments); | 68 try |
69 { | |
70 timeoutThread = new TimeoutThread(v8::Isolate::GetCurrent(), arguments); | |
71 } | |
72 catch (const std::exception& e) | |
73 { | |
74 return v8::ThrowException(v8::String::New(e.what())); | |
75 } | |
57 timeoutThread->Start(); | 76 timeoutThread->Start(); |
58 | 77 |
59 // We should actually return the timer ID here, which could be | 78 // We should actually return the timer ID here, which could be |
60 // used via clearTimeout(). But since we don't seem to need | 79 // used via clearTimeout(). But since we don't seem to need |
61 // clearTimeout(), we can safe that for later. | 80 // clearTimeout(), we can save that for later. |
Wladimir Palant
2013/04/08 08:36:00
safe => save?
Felix Dahlke
2013/04/08 13:07:49
Yes, of course.
| |
62 return v8::Undefined(); | 81 return v8::Undefined(); |
63 } | 82 } |
64 } | 83 } |
65 | 84 |
66 v8::Handle<v8::ObjectTemplate> GlobalJsObject::Create( | 85 v8::Handle<v8::ObjectTemplate> GlobalJsObject::Create( |
67 ErrorCallback& errorCallback) | 86 ErrorCallback& errorCallback) |
68 { | 87 { |
69 const v8::Locker locker(v8::Isolate::GetCurrent()); | 88 const v8::Locker locker(v8::Isolate::GetCurrent()); |
70 v8::HandleScope handleScope; | 89 v8::HandleScope handleScope; |
71 const v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); | 90 const v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); |
72 const v8::Handle<v8::ObjectTemplate> console = | 91 const v8::Handle<v8::ObjectTemplate> console = |
73 AdblockPlus::ConsoleJsObject::Create(errorCallback); | 92 AdblockPlus::ConsoleJsObject::Create(errorCallback); |
74 global->Set(v8::String::New("console"), console); | 93 global->Set(v8::String::New("console"), console); |
75 const v8::Handle<v8::FunctionTemplate> setTimeoutFunction = | 94 const v8::Handle<v8::FunctionTemplate> setTimeoutFunction = |
76 v8::FunctionTemplate::New(SetTimeoutCallback); | 95 v8::FunctionTemplate::New(SetTimeoutCallback); |
77 global->Set(v8::String::New("setTimeout"), setTimeoutFunction); | 96 global->Set(v8::String::New("setTimeout"), setTimeoutFunction); |
78 return handleScope.Close(global); | 97 return handleScope.Close(global); |
79 } | 98 } |
LEFT | RIGHT |