Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/GlobalJsObject.cpp

Issue 29370876: Issue #4692, #3595 - Stop sleeping in the implementation of `SetTimeout`
Patch Set: Created Jan. 9, 2017, 1:22 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/GlobalJsObject.h ('k') | src/JsEngine.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include <stdexcept>
19 #include <thread>
20 #include <vector>
21
22 #include <AdblockPlus/JsValue.h>
23
24 #include "AppInfoJsObject.h" 18 #include "AppInfoJsObject.h"
25 #include "ConsoleJsObject.h" 19 #include "ConsoleJsObject.h"
26 #include "FileSystemJsObject.h"
27 #include "GlobalJsObject.h" 20 #include "GlobalJsObject.h"
28 #include "JsEngineInternal.h"
29 #include "JsEngineTransition.h"
30 #include "Scheduler.h"
31 #include "Utils.h" 21 #include "Utils.h"
32 #include "WebRequestJsObject.h"
33 22
34 using namespace AdblockPlus; 23 using namespace AdblockPlus;
35 24
36 namespace 25 namespace
37 { 26 {
38 class TimeoutTask
39 {
40 typedef int64_t delayType; // return type of v8::Value::GetInteger()
41 public:
42 TimeoutTask(
43 JsEngineInternal *engine,
44 V8PersistentNG<v8::Function> function,
45 delayType delay,
46 PersistentValueArray functionArguments
47 ) :
48 jsEnginePtr(engine->shared_from_this()),
49 function(function),
50 delay(delay),
51 functionArguments(std::move(functionArguments))
52 {}
53
54 void operator()()
55 {
56 std::this_thread::sleep_for(std::chrono::milliseconds(delay));
57
58 auto engine = ToInternal(jsEnginePtr);
59 V8ExecutionScope sentry(engine);
60 auto isolate = jsEnginePtr->GetIsolate();
61 engine->ApplyFunction(function.Get(isolate), functionArguments.GetAsLocal( isolate));
62 }
63
64 private:
65 /**
66 * shared_ptr ensures the engine remains in existence
67 * while we're waiting for the task to complete.
68 * The scheduler ought to undertake this responsibility,
69 * but until then we must do it ourselves.
70 */
71 AdblockPlus::JsEnginePtr jsEnginePtr;
72 V8PersistentNG<v8::Function> function;
73 delayType delay;
74 PersistentValueArray functionArguments;
75 };
76 }
77
78 /**
79 * Callback function registered to v8 to implement `SetTimeout`
80 *
81 * Note that this implementation does not support the "evaluate code" version
82 * of `SetTimeout`, only the "apply function" version.
83 *
84 * \par Reference
85 * https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
86 */
87 v8::Handle<v8::Value> CallbackForSetTimeout(const v8::Arguments& arguments)
88 {
89 std::shared_ptr<TimeoutTask> timeoutTask;
90 auto engine = JsEngineInternal::ExtractEngine(arguments);
91 try
92 {
93 if (arguments.Length() < 2)
94 {
95 throw std::runtime_error("setTimeout: must have at least 2 arguments");
96 }
97 if (!arguments[0]->IsFunction())
98 {
99 throw std::runtime_error("setTimeout: argument 1 must be a function");
100 }
101 auto isolate = engine->GetIsolate();
102 size_t n = arguments.Length() - 2;
103 PersistentValueArray functionArguments(n);
104 for (size_t i = 0; i < n; i++)
105 {
106 functionArguments[i] = V8PersistentNG<v8::Value>(isolate, arguments[i + 2] );
107 }
108 timeoutTask = std::make_shared<TimeoutTask>(
109 engine,
110 V8PersistentNG<v8::Function>(isolate, v8::Local<v8::Function>::Cast(argume nts[0])),
111 arguments[1]->IntegerValue(),
112 std::move(functionArguments));
113 }
114 catch (const std::exception& e)
115 {
116 v8::Isolate* isolate = arguments.GetIsolate();
117 return v8::ThrowException(Utils::ToV8String(isolate, e.what()));
118 }
119 StartImmediatelyInSingleUseDetachedThread(MakeHeapFunction(timeoutTask));
120
121 // We should actually return the timer ID here, which could be
122 // used via clearTimeout(). But since we don't seem to need
123 // clearTimeout(), we can save that for later.
124 return v8::Undefined();
125 }
126
127 namespace
128 {
129 v8::Handle<v8::Value> TriggerEventCallback(const v8::Arguments& arguments) 27 v8::Handle<v8::Value> TriggerEventCallback(const v8::Arguments& arguments)
130 { 28 {
131 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments); 29 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg uments);
132 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); 30 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments);
133 if (converted.size() < 1) 31 if (converted.size() < 1)
134 { 32 {
135 v8::Isolate* isolate = arguments.GetIsolate(); 33 v8::Isolate* isolate = arguments.GetIsolate();
136 return v8::ThrowException(Utils::ToV8String(isolate, 34 return v8::ThrowException(Utils::ToV8String(isolate,
137 "_triggerEvent expects at least one parameter")); 35 "_triggerEvent expects at least one parameter"));
138 } 36 }
139 std::string eventName = converted.front()->AsString(); 37 std::string eventName = converted.front()->AsString();
140 converted.erase(converted.begin()); 38 converted.erase(converted.begin());
141 jsEngine->TriggerEvent(eventName, converted); 39 jsEngine->TriggerEvent(eventName, converted);
142 return v8::Undefined(); 40 return v8::Undefined();
143 } 41 }
144 } 42 }
145 43
146 JsValuePtr AdblockPlus::GlobalJsObject::Setup(JsEnginePtr jsEngine, const AppInf o& appInfo, 44 JsValuePtr AdblockPlus::GlobalJsObject::Setup(JsEnginePtr jsEngine, const AppInf o& appInfo,
147 JsValuePtr obj) 45 JsValuePtr obj)
148 { 46 {
149 obj->SetProperty("_triggerEvent", jsEngine->NewCallback(::TriggerEventCallback )); 47 obj->SetProperty("_triggerEvent", jsEngine->NewCallback(::TriggerEventCallback ));
150 obj->SetProperty("console", 48 obj->SetProperty("console",
151 ConsoleJsObject::Setup(jsEngine, jsEngine->NewObject())); 49 ConsoleJsObject::Setup(jsEngine, jsEngine->NewObject()));
152 obj->SetProperty("_appInfo", 50 obj->SetProperty("_appInfo",
153 AppInfoJsObject::Setup(jsEngine, appInfo, jsEngine->NewObject())); 51 AppInfoJsObject::Setup(jsEngine, appInfo, jsEngine->NewObject()));
154 return obj; 52 return obj;
155 } 53 }
OLDNEW
« no previous file with comments | « src/GlobalJsObject.h ('k') | src/JsEngine.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld