| OLD | NEW |
| 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 <AdblockPlus/FileSystem.h> | 18 #include <AdblockPlus/FileSystem.h> |
| 19 #include <stdexcept> | 19 #include <stdexcept> |
| 20 #include <sstream> | 20 #include <sstream> |
| 21 #include <vector> | 21 #include <vector> |
| 22 | 22 |
| 23 #include <AdblockPlus/JsValue.h> | 23 #include <AdblockPlus/JsValue.h> |
| 24 #include "FileSystemJsObject.h" | 24 #include "FileSystemJsObject.h" |
| 25 #include "JsContext.h" | 25 #include "JsContext.h" |
| 26 #include "JsEngineTransition.h" |
| 26 #include "Scheduler.h" | 27 #include "Scheduler.h" |
| 27 #include "Utils.h" | 28 #include "Utils.h" |
| 29 #include "Value.h" |
| 28 | 30 |
| 29 using namespace AdblockPlus; | 31 using namespace AdblockPlus; |
| 30 | 32 |
| 31 namespace | 33 namespace |
| 32 { | 34 { |
| 33 class IoTask | 35 class ReadTask |
| 34 { | 36 { |
| 35 protected: | 37 /** |
| 36 virtual void operator()() = 0; | 38 * Shared pointer keeps engine in existence for task thread. |
| 39 */ |
| 37 JsEnginePtr jsEngine; | 40 JsEnginePtr jsEngine; |
| 38 FileSystemPtr fileSystem; | 41 std::string path; |
| 39 JsValuePtr callback; | 42 V8PersistentNG<v8::Function> callbackFunction; |
| 40 | 43 |
| 41 public: | 44 public: |
| 42 IoTask(JsEnginePtr jsEngine, JsValuePtr callback) | 45 ReadTask(JsEngineInternal* engine, const std::string& path, |
| 43 : jsEngine(jsEngine), fileSystem(jsEngine->GetFileSystem()), | 46 V8PersistentNG<v8::Function> callbackFunction) |
| 44 callback(callback) | 47 : jsEngine(engine->shared_from_this()), path(path), |
| 45 { | 48 callbackFunction(callbackFunction) |
| 46 } | 49 {} |
| 47 | |
| 48 virtual ~IoTask() {} | |
| 49 }; | |
| 50 | |
| 51 class ReadTask : public IoTask | |
| 52 { | |
| 53 public: | |
| 54 ReadTask(JsEnginePtr jsEngine, JsValuePtr callback, | |
| 55 const std::string& path) | |
| 56 : IoTask(jsEngine, callback), path(path) | |
| 57 { | |
| 58 } | |
| 59 | 50 |
| 60 void operator()() | 51 void operator()() |
| 61 { | 52 { |
| 53 JsEngineInternal* engine = ToInternal(jsEngine); |
| 62 std::string content; | 54 std::string content; |
| 63 std::string error; | 55 std::string error; |
| 56 // Read operation is long-lived. Do not lock engine during it. |
| 64 try | 57 try |
| 65 { | 58 { |
| 66 std::shared_ptr<std::istream> stream = fileSystem->Read(path); | 59 std::shared_ptr<std::istream> stream = engine->GetFileSystem()->Read(pat
h); |
| 67 content = Utils::Slurp(*stream); | 60 content = Utils::Slurp(*stream); |
| 68 } | 61 } |
| 69 catch (std::exception& e) | 62 catch (std::exception& e) |
| 70 { | 63 { |
| 71 error = e.what(); | 64 error = e.what(); |
| 72 } | 65 } |
| 73 catch (...) | 66 catch (...) |
| 74 { | 67 { |
| 75 error = "Unknown error while reading from " + path; | 68 error = "Unknown error while reading from " + path; |
| 76 } | 69 } |
| 77 | 70 // Call back with the results of the read operation |
| 78 const JsContext context(jsEngine); | 71 V8ExecutionScope scope(engine); |
| 79 JsValuePtr result = jsEngine->NewObject(); | 72 auto callbackArguments = v8::Object::New(); |
| 80 result->SetProperty("content", content); | 73 callbackArguments->Set(engine->ToV8String("content"), engine->ToV8String(c
ontent)); |
| 81 result->SetProperty("error", error); | 74 callbackArguments->Set(engine->ToV8String("error"), engine->ToV8String(err
or)); |
| 82 JsValueList params; | 75 auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| 83 params.push_back(result); | 76 args[0] = callbackArguments; |
| 84 callback->Call(params); | 77 engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
e(args)); |
| 85 } | 78 } |
| 86 | |
| 87 private: | |
| 88 std::string path; | |
| 89 }; | 79 }; |
| 90 | 80 |
| 91 class WriteTask : public IoTask | 81 class WriteTask |
| 92 { | 82 { |
| 83 /** |
| 84 * Shared pointer keeps engine in existence for task thread. |
| 85 */ |
| 86 JsEnginePtr jsEngine; |
| 87 std::string path; |
| 88 std::string content; |
| 89 V8PersistentNG<v8::Function> callbackFunction; |
| 93 public: | 90 public: |
| 94 WriteTask(JsEnginePtr jsEngine, JsValuePtr callback, | 91 WriteTask(JsEngineInternal* engine, |
| 95 const std::string& path, const std::string& content) | 92 const std::string& path, const std::string& content, |
| 96 : IoTask(jsEngine, callback), path(path), content(content) | 93 V8PersistentNG<v8::Function> callbackFunction) |
| 97 { | 94 : jsEngine(engine->shared_from_this()), path(path), content(content), |
| 98 } | 95 callbackFunction(callbackFunction) |
| 96 {} |
| 99 | 97 |
| 100 void operator()() | 98 void operator()() |
| 101 { | 99 { |
| 100 JsEngineInternal* engine = ToInternal(jsEngine); |
| 102 std::string error; | 101 std::string error; |
| 102 // Write operation is long-lived. Do not lock engine during it. |
| 103 try | 103 try |
| 104 { | 104 { |
| 105 std::shared_ptr<std::iostream> stream(new std::stringstream); | 105 std::shared_ptr<std::iostream> stream(new std::stringstream); |
| 106 *stream << content; | 106 *stream << content; |
| 107 fileSystem->Write(path, stream); | 107 engine->GetFileSystem()->Write(path, stream); |
| 108 } | 108 } |
| 109 catch (std::exception& e) | 109 catch (std::exception& e) |
| 110 { | 110 { |
| 111 error = e.what(); | 111 error = e.what(); |
| 112 } | 112 } |
| 113 catch (...) | 113 catch (...) |
| 114 { | 114 { |
| 115 error = "Unknown error while writing to " + path; | 115 error = "Unknown error while writing to " + path; |
| 116 } | 116 } |
| 117 | 117 // Apply the callback function |
| 118 const JsContext context(jsEngine); | 118 V8ExecutionScope scope(engine); |
| 119 JsValuePtr errorValue = jsEngine->NewValue(error); | 119 auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| 120 JsValueList params; | 120 args[0] = engine->ToV8String(error); |
| 121 params.push_back(errorValue); | 121 engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
e(args)); |
| 122 callback->Call(params); | |
| 123 } | 122 } |
| 124 | |
| 125 private: | |
| 126 std::string path; | |
| 127 std::string content; | |
| 128 }; | 123 }; |
| 129 | 124 |
| 130 class MoveTask : public IoTask | 125 class MoveTask |
| 131 { | 126 { |
| 127 /** |
| 128 * Shared pointer keeps engine in existence for task thread. |
| 129 */ |
| 130 JsEnginePtr jsEngine; |
| 131 std::string fromPath; |
| 132 std::string toPath; |
| 133 V8PersistentNG<v8::Function> callbackFunction; |
| 134 |
| 132 public: | 135 public: |
| 133 MoveTask(JsEnginePtr jsEngine, JsValuePtr callback, | 136 MoveTask(JsEngineInternal* engine, const std::string& fromPath, const std::s
tring& toPath, |
| 134 const std::string& fromPath, const std::string& toPath) | 137 V8PersistentNG<v8::Function> callbackFunction) |
| 135 : IoTask(jsEngine, callback), fromPath(fromPath), toPath(toPath) | 138 : jsEngine(engine->shared_from_this()), fromPath(fromPath), toPath(toPath)
, |
| 136 { | 139 callbackFunction(callbackFunction) |
| 137 } | 140 {} |
| 138 | 141 |
| 139 void operator()() | 142 void operator()() |
| 140 { | 143 { |
| 144 JsEngineInternal* engine(ToInternal(jsEngine)); |
| 141 std::string error; | 145 std::string error; |
| 142 try | 146 try |
| 143 { | 147 { |
| 144 fileSystem->Move(fromPath, toPath); | 148 engine->GetFileSystem()->Move(fromPath, toPath); |
| 145 } | 149 } |
| 146 catch (std::exception& e) | 150 catch (std::exception& e) |
| 147 { | 151 { |
| 148 error = e.what(); | 152 error = e.what(); |
| 149 } | 153 } |
| 150 catch (...) | 154 catch (...) |
| 151 { | 155 { |
| 152 error = "Unknown error while moving " + fromPath + " to " + toPath; | 156 error = "Unknown error while moving " + fromPath + " to " + toPath; |
| 153 } | 157 } |
| 154 | 158 V8ExecutionScope scope(engine); |
| 155 const JsContext context(jsEngine); | 159 auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| 156 JsValuePtr errorValue = jsEngine->NewValue(error); | 160 args[0] = engine->ToV8String(error); |
| 157 JsValueList params; | 161 engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
e(args)); |
| 158 params.push_back(errorValue); | |
| 159 callback->Call(params); | |
| 160 } | 162 } |
| 161 | |
| 162 private: | |
| 163 std::string fromPath; | |
| 164 std::string toPath; | |
| 165 }; | 163 }; |
| 166 | 164 |
| 167 class RemoveTask : public IoTask | 165 class RemoveTask |
| 168 { | 166 { |
| 167 /** |
| 168 * Shared pointer keeps engine in existence for task thread. |
| 169 */ |
| 170 JsEnginePtr jsEngine; |
| 171 std::string path; |
| 172 V8PersistentNG<v8::Function> callbackFunction; |
| 173 |
| 169 public: | 174 public: |
| 170 RemoveTask(JsEnginePtr jsEngine, JsValuePtr callback, | 175 RemoveTask(JsEngineInternal *engine, const std::string& path, |
| 171 const std::string& path) | 176 V8PersistentNG<v8::Function> callbackFunction) |
| 172 : IoTask(jsEngine, callback), path(path) | 177 : jsEngine(engine->shared_from_this()), path(path), |
| 173 { | 178 callbackFunction(callbackFunction) |
| 174 } | 179 {} |
| 175 | 180 |
| 176 void operator()() | 181 void operator()() |
| 177 { | 182 { |
| 183 JsEngineInternal* engine(ToInternal(jsEngine)); |
| 178 std::string error; | 184 std::string error; |
| 179 try | 185 try |
| 180 { | 186 { |
| 181 fileSystem->Remove(path); | 187 engine->GetFileSystem()->Remove(path); |
| 182 } | 188 } |
| 183 catch (std::exception& e) | 189 catch (std::exception& e) |
| 184 { | 190 { |
| 185 error = e.what(); | 191 error = e.what(); |
| 186 } | 192 } |
| 187 catch (...) | 193 catch (...) |
| 188 { | 194 { |
| 189 error = "Unknown error while removing " + path; | 195 error = "Unknown error while removing " + path; |
| 190 } | 196 } |
| 191 | 197 V8ExecutionScope scope(engine); |
| 192 const JsContext context(jsEngine); | 198 auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| 193 JsValuePtr errorValue = jsEngine->NewValue(error); | 199 args[0] = engine->ToV8String(error); |
| 194 JsValueList params; | 200 engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
e(args)); |
| 195 params.push_back(errorValue); | |
| 196 callback->Call(params); | |
| 197 } | 201 } |
| 198 | |
| 199 private: | |
| 200 std::string path; | |
| 201 }; | 202 }; |
| 202 | 203 |
| 204 class StatTask |
| 205 { |
| 206 /** |
| 207 * Shared pointer keeps engine in existence for task thread. |
| 208 */ |
| 209 JsEnginePtr jsEngine; |
| 210 std::string path; |
| 211 V8PersistentNG<v8::Function> callbackFunction; |
| 203 | 212 |
| 204 class StatTask : public IoTask | |
| 205 { | |
| 206 public: | 213 public: |
| 207 StatTask(JsEnginePtr jsEngine, JsValuePtr callback, | 214 StatTask(JsEngineInternal* engine, const std::string& path, |
| 208 const std::string& path) | 215 V8PersistentNG<v8::Function> callbackFunction) |
| 209 : IoTask(jsEngine, callback), path(path) | 216 : jsEngine(engine->shared_from_this()), path(path), |
| 210 { | 217 callbackFunction(callbackFunction) |
| 211 } | 218 {} |
| 212 | 219 |
| 213 void operator()() | 220 void operator()() |
| 214 { | 221 { |
| 222 JsEngineInternal* engine(ToInternal(jsEngine)); |
| 215 std::string error; | 223 std::string error; |
| 216 FileSystem::StatResult statResult; | 224 FileSystem::StatResult statResult; |
| 217 try | 225 try |
| 218 { | 226 { |
| 219 statResult = fileSystem->Stat(path); | 227 statResult = engine->GetFileSystem()->Stat(path); |
| 220 } | 228 } |
| 221 catch (std::exception& e) | 229 catch (std::exception& e) |
| 222 { | 230 { |
| 223 error = e.what(); | 231 error = e.what(); |
| 224 } | 232 } |
| 225 catch (...) | 233 catch (...) |
| 226 { | 234 { |
| 227 error = "Unknown error while calling stat on " + path; | 235 error = "Unknown error while calling stat on " + path; |
| 228 } | 236 } |
| 229 | 237 V8ExecutionScope scope(engine); |
| 230 const JsContext context(jsEngine); | 238 auto callbackArgument(v8::Object::New()); |
| 231 JsValuePtr result = jsEngine->NewObject(); | 239 callbackArgument->Set(engine->ToV8String("exists"), v8::Boolean::New(statR
esult.exists)); |
| 232 result->SetProperty("exists", statResult.exists); | 240 callbackArgument->Set(engine->ToV8String("isFile"), v8::Boolean::New(statR
esult.isFile)); |
| 233 result->SetProperty("isFile", statResult.isFile); | 241 callbackArgument->Set(engine->ToV8String("isDirectory"), v8::Boolean::New(
statResult.isDirectory)); |
| 234 result->SetProperty("isDirectory", statResult.isDirectory); | 242 callbackArgument->Set(engine->ToV8String("lastModified"), v8::Number::New(
statResult.lastModified)); |
| 235 result->SetProperty("lastModified", statResult.lastModified); | 243 callbackArgument->Set(engine->ToV8String("error"), engine->ToV8String(erro
r)); |
| 236 result->SetProperty("error", error); | 244 auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| 237 | 245 args[0] = callbackArgument; |
| 238 JsValueList params; | 246 engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::mov
e(args)); |
| 239 params.push_back(result); | 247 } |
| 240 callback->Call(params); | |
| 241 } | |
| 242 | |
| 243 private: | |
| 244 std::string path; | |
| 245 }; | 248 }; |
| 246 | 249 } |
| 247 v8::Handle<v8::Value> ReadCallback(const v8::Arguments& arguments) | 250 |
| 248 { | 251 v8::Handle<v8::Value> ReadCallback(const v8::Arguments& arguments) |
| 249 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
uments); | 252 { |
| 250 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 253 auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| 251 | 254 std::shared_ptr<ReadTask> readTask; |
| 255 try |
| 256 { |
| 257 if (arguments.Length() != 2) |
| 258 { |
| 259 throw std::runtime_error("_fileSystem.read requires 2 parameters"); |
| 260 } |
| 261 bool argumentIsString; |
| 262 std::string firstArgument; |
| 263 std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| 264 if (!argumentIsString) |
| 265 { |
| 266 throw std::runtime_error("First argument to _fileSystem.read must be a str
ing"); |
| 267 } |
| 268 if (!arguments[1]->IsFunction()) |
| 269 { |
| 270 throw std::runtime_error("Second argument to _fileSystem.read must be a fu
nction"); |
| 271 } |
| 272 readTask = std::make_shared<ReadTask>(engine, firstArgument, |
| 273 V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>
::Cast(arguments[1]))); |
| 274 } |
| 275 catch (const std::exception& e) |
| 276 { |
| 277 return v8::ThrowException(engine->ToV8String(e.what())); |
| 278 } |
| 279 // Run the task |
| 280 engine->Schedule(AdblockPlus::MakeHeapFunction(readTask), AdblockPlus::Immedia
teSingleUseThread); |
| 281 return v8::Undefined(); |
| 282 } |
| 283 |
| 284 v8::Handle<v8::Value> WriteCallback(const v8::Arguments& arguments) |
| 285 { |
| 286 auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| 287 std::shared_ptr<WriteTask> writeTask; |
| 288 try |
| 289 { |
| 252 v8::Isolate* isolate = arguments.GetIsolate(); | 290 v8::Isolate* isolate = arguments.GetIsolate(); |
| 253 if (converted.size() != 2) | 291 |
| 254 return v8::ThrowException(Utils::ToV8String(isolate, | 292 if (arguments.Length() != 3) |
| 255 "_fileSystem.read requires 2 parameters")); | 293 { |
| 256 if (!converted[1]->IsFunction()) | 294 throw std::exception("_fileSystem.write requires 3 parameters"); |
| 257 return v8::ThrowException(Utils::ToV8String(isolate, | 295 } |
| 258 "Second argument to _fileSystem.read must be a function")); | 296 bool argumentIsString; |
| 259 const auto readTask = std::make_shared<ReadTask>(jsEngine, converted[1], | 297 std::string firstArgument; |
| 260 converted[0]->AsString()); | 298 std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| 261 jsEngine->Schedule(AdblockPlus::MakeHeapFunction(readTask), AdblockPlus::Imm
ediateSingleUseThread); | 299 if (!argumentIsString) |
| 262 return v8::Undefined(); | 300 { |
| 263 } | 301 throw std::runtime_error("First argument to _fileSystem.write must be a st
ring"); |
| 264 | 302 } |
| 265 v8::Handle<v8::Value> WriteCallback(const v8::Arguments& arguments) | 303 std::string secondArgument; |
| 266 { | 304 std::tie(argumentIsString, secondArgument) = ConvertString(arguments[1]); |
| 267 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
uments); | 305 if (!argumentIsString) |
| 268 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 306 { |
| 269 | 307 throw std::runtime_error("Second argument to _fileSystem.write must be a s
tring"); |
| 270 v8::Isolate* isolate = arguments.GetIsolate(); | 308 } |
| 271 if (converted.size() != 3) | 309 if (!arguments[2]->IsFunction()) |
| 272 return v8::ThrowException(Utils::ToV8String(isolate, | 310 { |
| 273 "_fileSystem.write requires 3 parameters")); | 311 throw std::runtime_error("Third argument to _fileSystem.write must be a fu
nction"); |
| 274 if (!converted[2]->IsFunction()) | 312 } |
| 275 return v8::ThrowException(Utils::ToV8String(isolate, | 313 writeTask = std::make_shared<WriteTask>(engine, firstArgument, secondArgumen
t, |
| 276 "Third argument to _fileSystem.write must be a function")); | 314 V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>
::Cast(arguments[2]))); |
| 277 const auto writeTask = std::make_shared<WriteTask>(jsEngine, converted[2], | 315 } |
| 278 converted[0]->AsString(), converted[1]->AsString()); | 316 catch (const std::exception& e) |
| 279 jsEngine->Schedule(AdblockPlus::MakeHeapFunction(writeTask), AdblockPlus::Im
mediateSingleUseThread); | 317 { |
| 280 return v8::Undefined(); | 318 return v8::ThrowException(engine->ToV8String(e.what())); |
| 281 } | 319 } |
| 282 | 320 engine->Schedule(AdblockPlus::MakeHeapFunction(writeTask), AdblockPlus::Immedi
ateSingleUseThread); |
| 283 v8::Handle<v8::Value> MoveCallback(const v8::Arguments& arguments) | 321 return v8::Undefined(); |
| 284 { | 322 } |
| 285 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
uments); | 323 |
| 286 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 324 v8::Handle<v8::Value> MoveCallback(const v8::Arguments& arguments) |
| 287 | 325 { |
| 288 v8::Isolate* isolate = arguments.GetIsolate(); | 326 auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| 289 if (converted.size() != 3) | 327 std::shared_ptr<MoveTask> moveTask; |
| 290 return v8::ThrowException(Utils::ToV8String(isolate, | 328 std::string firstArgument, secondArgument; |
| 291 "_fileSystem.move requires 3 parameters")); | 329 try |
| 292 if (!converted[2]->IsFunction()) | 330 { |
| 293 return v8::ThrowException(Utils::ToV8String(isolate, | 331 if (arguments.Length() != 3) |
| 294 "Third argument to _fileSystem.move must be a function")); | 332 { |
| 295 const auto moveTask = std::make_shared<MoveTask>(jsEngine, converted[2], | 333 throw std::runtime_error("_fileSystem.move requires 3 parameters"); |
| 296 converted[0]->AsString(), converted[1]->AsString()); | 334 } |
| 297 jsEngine->Schedule(AdblockPlus::MakeHeapFunction(moveTask), AdblockPlus::Imm
ediateSingleUseThread); | 335 bool argumentIsString; |
| 298 return v8::Undefined(); | 336 std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| 299 } | 337 if (!argumentIsString) |
| 300 | 338 { |
| 301 v8::Handle<v8::Value> RemoveCallback(const v8::Arguments& arguments) | 339 throw std::runtime_error("First argument to _fileSystem.write must be a st
ring"); |
| 302 { | 340 } |
| 303 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
uments); | 341 std::tie(argumentIsString, secondArgument) = ConvertString(arguments[1]); |
| 304 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 342 if (!argumentIsString) |
| 305 | 343 { |
| 306 v8::Isolate* isolate = arguments.GetIsolate(); | 344 throw std::runtime_error("Second argument to _fileSystem.write must be a s
tring"); |
| 307 if (converted.size() != 2) | 345 } |
| 308 return v8::ThrowException(Utils::ToV8String(isolate, | 346 if (!arguments[2]->IsFunction()) |
| 309 "_fileSystem.remove requires 2 parameters")); | 347 { |
| 310 if (!converted[1]->IsFunction()) | 348 throw std::runtime_error("Third argument to _fileSystem.move must be a fun
ction"); |
| 311 return v8::ThrowException(Utils::ToV8String(isolate, | 349 } |
| 312 "Second argument to _fileSystem.remove must be a function")); | 350 } |
| 313 const auto removeTask = std::make_shared<RemoveTask>(jsEngine, converted[1], | 351 catch (const std::exception& e) |
| 314 converted[0]->AsString()); | 352 { |
| 315 jsEngine->Schedule(AdblockPlus::MakeHeapFunction(removeTask), AdblockPlus::I
mmediateSingleUseThread); | 353 return v8::ThrowException(engine->ToV8String(e.what())); |
| 316 return v8::Undefined(); | 354 } |
| 317 } | 355 // Run the task |
| 318 | 356 moveTask = std::make_shared<MoveTask>(engine, firstArgument, secondArgument, |
| 319 v8::Handle<v8::Value> StatCallback(const v8::Arguments& arguments) | 357 V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::
Cast(arguments[2]))); |
| 320 { | 358 engine->Schedule(AdblockPlus::MakeHeapFunction(moveTask), AdblockPlus::Immedia
teSingleUseThread); |
| 321 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
uments); | 359 return v8::Undefined(); |
| 322 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 360 } |
| 323 | 361 |
| 324 v8::Isolate* isolate = arguments.GetIsolate(); | 362 v8::Handle<v8::Value> RemoveCallback(const v8::Arguments& arguments) |
| 325 if (converted.size() != 2) | 363 { |
| 326 return v8::ThrowException(Utils::ToV8String(isolate, | 364 auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| 327 "_fileSystem.stat requires 2 parameters")); | 365 std::shared_ptr<RemoveTask> removeTask; |
| 328 if (!converted[1]->IsFunction()) | 366 std::string firstArgument; |
| 329 return v8::ThrowException(Utils::ToV8String(isolate, | 367 try |
| 330 "Second argument to _fileSystem.stat must be a function")); | 368 { |
| 331 const auto statTask = std::make_shared<StatTask>(jsEngine, converted[1], | 369 if (arguments.Length() != 2) |
| 332 converted[0]->AsString()); | 370 { |
| 333 jsEngine->Schedule(AdblockPlus::MakeHeapFunction(statTask), AdblockPlus::Imm
ediateSingleUseThread); | 371 throw std::runtime_error("_fileSystem.remove requires 2 parameters"); |
| 334 return v8::Undefined(); | 372 } |
| 335 } | 373 bool argumentIsString; |
| 336 | 374 std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| 337 v8::Handle<v8::Value> ResolveCallback(const v8::Arguments& arguments) | 375 if (!argumentIsString) |
| 338 { | 376 { |
| 339 AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arg
uments); | 377 throw std::runtime_error("First argument to _fileSystem.remove must be a s
tring"); |
| 340 AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); | 378 } |
| 341 | 379 if (!arguments[1]->IsFunction()) |
| 342 v8::Isolate* isolate = arguments.GetIsolate(); | 380 { |
| 343 if (converted.size() != 1) | 381 throw std::runtime_error("Second argument to _fileSystem.remove must be a
function"); |
| 344 return v8::ThrowException(Utils::ToV8String(isolate, | 382 } |
| 345 "_fileSystem.resolve requires 1 parameter")); | 383 } |
| 346 | 384 catch (const std::exception& e) |
| 347 std::string resolved = jsEngine->GetFileSystem()->Resolve(converted[0]->AsSt
ring()); | 385 { |
| 348 | 386 return v8::ThrowException(engine->ToV8String(e.what())); |
| 349 return Utils::ToV8String(isolate, resolved); | 387 } |
| 350 } | 388 // Run the task |
| 351 | 389 removeTask = std::make_shared<RemoveTask>(engine, firstArgument, |
| 352 } | 390 V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::
Cast(arguments[1]))); |
| 353 | 391 engine->Schedule(AdblockPlus::MakeHeapFunction(removeTask), AdblockPlus::Immed
iateSingleUseThread); |
| 354 | 392 return v8::Undefined(); |
| 355 JsValuePtr FileSystemJsObject::Setup(JsEnginePtr jsEngine, JsValuePtr obj) | 393 } |
| 356 { | 394 |
| 357 obj->SetProperty("read", jsEngine->NewCallback(::ReadCallback)); | 395 v8::Handle<v8::Value> StatCallback(const v8::Arguments& arguments) |
| 358 obj->SetProperty("write", jsEngine->NewCallback(::WriteCallback)); | 396 { |
| 359 obj->SetProperty("move", jsEngine->NewCallback(::MoveCallback)); | 397 auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| 360 obj->SetProperty("remove", jsEngine->NewCallback(::RemoveCallback)); | 398 std::shared_ptr<StatTask> statTask; |
| 361 obj->SetProperty("stat", jsEngine->NewCallback(::StatCallback)); | 399 std::string firstArgument; |
| 362 obj->SetProperty("resolve", jsEngine->NewCallback(::ResolveCallback)); | 400 try |
| 363 return obj; | 401 { |
| 364 } | 402 if (arguments.Length() != 2) |
| 403 { |
| 404 throw std::runtime_error("_fileSystem.stat requires 2 parameters"); |
| 405 } |
| 406 bool argumentIsString; |
| 407 std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| 408 if (!argumentIsString) |
| 409 { |
| 410 throw std::runtime_error("First argument to _fileSystem.stat must be a str
ing"); |
| 411 } |
| 412 if (!arguments[1]->IsFunction()) |
| 413 { |
| 414 throw std::runtime_error("Second argument to _fileSystem.stat must be a fu
nction"); |
| 415 } |
| 416 } |
| 417 catch (const std::exception& e) |
| 418 { |
| 419 return v8::ThrowException(engine->ToV8String(e.what())); |
| 420 } |
| 421 // Run the task |
| 422 statTask = std::make_shared<StatTask>(engine, firstArgument, |
| 423 V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::
Cast(arguments[1]))); |
| 424 engine->Schedule(AdblockPlus::MakeHeapFunction(statTask), AdblockPlus::Immedia
teSingleUseThread); |
| 425 return v8::Undefined(); |
| 426 } |
| 427 |
| 428 v8::Handle<v8::Value> ResolveCallback(const v8::Arguments& arguments) |
| 429 { |
| 430 auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| 431 std::string firstArgument; |
| 432 try |
| 433 { |
| 434 if (arguments.Length() != 1) |
| 435 { |
| 436 throw std::runtime_error("_fileSystem.resolve requires 1 parameter"); |
| 437 } |
| 438 bool argumentIsString; |
| 439 std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| 440 if (!argumentIsString) |
| 441 { |
| 442 throw std::runtime_error("First argument to _fileSystem.write must be a st
ring"); |
| 443 } |
| 444 } |
| 445 catch (const std::exception& e) |
| 446 { |
| 447 return v8::ThrowException(engine->ToV8String(e.what())); |
| 448 } |
| 449 /* |
| 450 * Make sure to perform long-lived file system operation with engine unlocked. |
| 451 */ |
| 452 std::string resolved = engine->GetFileSystem()->Resolve(firstArgument); |
| 453 return engine->ToV8String(resolved); |
| 454 } |
| OLD | NEW |