OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2017 Eyeo GmbH |
| 4 * |
| 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 |
| 7 * published by the Free Software Foundation. |
| 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 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/>. |
| 16 */ |
| 17 |
| 18 #include "JsEngineInternal.h" |
| 19 #include "JsEngineTransition.h" |
| 20 #include "Scheduler.h" |
| 21 #include "Timeout.h" |
| 22 #include "Utils.h" |
| 23 |
| 24 namespace |
| 25 { |
| 26 class TimeoutTask |
| 27 : public TaskFunctionInterface |
| 28 { |
| 29 typedef int64_t delayType; // return type of v8::Value::GetInteger() |
| 30 /** |
| 31 * shared_ptr ensures the engine remains in existence |
| 32 * while we're waiting for the task to complete. |
| 33 * The scheduler ought to undertake this responsibility, |
| 34 * but until then we must do it ourselves. |
| 35 */ |
| 36 JsEngineInternal* engine; |
| 37 V8PersistentNG<v8::Function> function; |
| 38 delayType delay; |
| 39 PersistentValueArray functionArguments; |
| 40 DelayedExecutor executor; |
| 41 |
| 42 void body() |
| 43 { |
| 44 V8ExecutionScope sentry(engine); |
| 45 auto isolate = engine->GetIsolate(); |
| 46 engine->ApplyFunction(function.Get(isolate), functionArguments.GetAsLocal(
isolate)); |
| 47 } |
| 48 |
| 49 public: |
| 50 TimeoutTask( |
| 51 JsEngineInternal *engine, |
| 52 V8PersistentNG<v8::Function> function, |
| 53 delayType delay, |
| 54 PersistentValueArray functionArguments |
| 55 ) : |
| 56 engine(engine), |
| 57 function(function), |
| 58 delay(delay), |
| 59 functionArguments(std::move(functionArguments)), |
| 60 executor([this]() { body(); }) |
| 61 {} |
| 62 |
| 63 void operator()() override |
| 64 { |
| 65 executor.RunWithDelay(std::chrono::milliseconds(delay)); |
| 66 } |
| 67 |
| 68 void Interrupt() override |
| 69 { |
| 70 executor.ForestallExecution(); |
| 71 } |
| 72 }; |
| 73 } |
| 74 |
| 75 /** |
| 76 * Callback function registered to v8 to implement `SetTimeout` |
| 77 * |
| 78 * Note that this implementation does not support the "evaluate code" version |
| 79 * of `SetTimeout`, only the "apply function" version. |
| 80 * |
| 81 * \par Reference |
| 82 * https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout |
| 83 */ |
| 84 v8::Handle<v8::Value> CallbackForSetTimeout(const v8::Arguments& arguments) |
| 85 { |
| 86 auto engine = JsEngineInternal::ExtractEngine(arguments); |
| 87 try |
| 88 { |
| 89 if (arguments.Length() < 2) |
| 90 { |
| 91 throw std::runtime_error("setTimeout: must have at least 2 arguments"); |
| 92 } |
| 93 if (!arguments[0]->IsFunction()) |
| 94 { |
| 95 throw std::runtime_error("setTimeout: argument 1 must be a function"); |
| 96 } |
| 97 auto isolate = engine->GetIsolate(); |
| 98 size_t n = arguments.Length() - 2; |
| 99 PersistentValueArray functionArguments(n); |
| 100 for (size_t i = 0; i < n; i++) |
| 101 { |
| 102 functionArguments[i] = V8PersistentNG<v8::Value>(isolate, arguments[i + 2]
); |
| 103 } |
| 104 /* |
| 105 * Run the task |
| 106 */ |
| 107 auto task(std::make_shared<TimeoutTask>(engine, |
| 108 V8PersistentNG<v8::Function>(isolate, v8::Local<v8::Function>::Cast(argume
nts[0])), |
| 109 arguments[1]->IntegerValue(), std::move(functionArguments))); |
| 110 engine->ScheduleTask(std::move(task), ImmediateSingleUseThread); |
| 111 // We should actually return the timer ID here, which could be |
| 112 // used via clearTimeout(). But since we don't seem to need |
| 113 // clearTimeout(), we can save that for later. |
| 114 return v8::Undefined(); |
| 115 } |
| 116 catch (const std::exception& e) |
| 117 { |
| 118 return v8::ThrowException(engine->ToV8String(e.what())); |
| 119 } |
| 120 } |
OLD | NEW |