| 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 |