| Index: src/FileSystemJsObject.cpp |
| =================================================================== |
| --- a/src/FileSystemJsObject.cpp |
| +++ b/src/FileSystemJsObject.cpp |
| @@ -23,47 +23,40 @@ |
| #include <AdblockPlus/JsValue.h> |
| #include "FileSystemJsObject.h" |
| #include "JsContext.h" |
| +#include "JsEngineTransition.h" |
| #include "Scheduler.h" |
| #include "Utils.h" |
| +#include "Value.h" |
| using namespace AdblockPlus; |
| namespace |
| { |
| - class IoTask |
| + class ReadTask |
| { |
| - protected: |
| - virtual void operator()() = 0; |
| + /** |
| + * Shared pointer keeps engine in existence for task thread. |
| + */ |
| JsEnginePtr jsEngine; |
| - FileSystemPtr fileSystem; |
| - JsValuePtr callback; |
| + std::string path; |
| + V8PersistentNG<v8::Function> callbackFunction; |
| public: |
| - IoTask(JsEnginePtr jsEngine, JsValuePtr callback) |
| - : jsEngine(jsEngine), fileSystem(jsEngine->GetFileSystem()), |
| - callback(callback) |
| - { |
| - } |
| - |
| - virtual ~IoTask() {} |
| - }; |
| - |
| - class ReadTask : public IoTask |
| - { |
| - public: |
| - ReadTask(JsEnginePtr jsEngine, JsValuePtr callback, |
| - const std::string& path) |
| - : IoTask(jsEngine, callback), path(path) |
| - { |
| - } |
| + ReadTask(JsEngineInternal* engine, const std::string& path, |
| + V8PersistentNG<v8::Function> callbackFunction) |
| + : jsEngine(engine->shared_from_this()), path(path), |
| + callbackFunction(callbackFunction) |
| + {} |
| void operator()() |
| { |
| + JsEngineInternal* engine = ToInternal(jsEngine); |
| std::string content; |
| std::string error; |
| + // Read operation is long-lived. Do not lock engine during it. |
| try |
| { |
| - std::shared_ptr<std::istream> stream = fileSystem->Read(path); |
| + std::shared_ptr<std::istream> stream = engine->GetFileSystem()->Read(path); |
| content = Utils::Slurp(*stream); |
| } |
| catch (std::exception& e) |
| @@ -72,39 +65,46 @@ |
| } |
| catch (...) |
| { |
| - error = "Unknown error while reading from " + path; |
| + error = "Unknown error while reading from " + path; |
| } |
| - |
| - const JsContext context(jsEngine); |
| - JsValuePtr result = jsEngine->NewObject(); |
| - result->SetProperty("content", content); |
| - result->SetProperty("error", error); |
| - JsValueList params; |
| - params.push_back(result); |
| - callback->Call(params); |
| + // Call back with the results of the read operation |
| + V8ExecutionScope scope(engine); |
| + auto callbackArguments = v8::Object::New(); |
| + callbackArguments->Set(engine->ToV8String("content"), engine->ToV8String(content)); |
| + callbackArguments->Set(engine->ToV8String("error"), engine->ToV8String(error)); |
| + auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| + args[0] = callbackArguments; |
| + engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::move(args)); |
| } |
| - |
| - private: |
| - std::string path; |
| }; |
| - class WriteTask : public IoTask |
| + class WriteTask |
| { |
| + /** |
| + * Shared pointer keeps engine in existence for task thread. |
| + */ |
| + JsEnginePtr jsEngine; |
| + std::string path; |
| + std::string content; |
| + V8PersistentNG<v8::Function> callbackFunction; |
| public: |
| - WriteTask(JsEnginePtr jsEngine, JsValuePtr callback, |
| - const std::string& path, const std::string& content) |
| - : IoTask(jsEngine, callback), path(path), content(content) |
| - { |
| - } |
| + WriteTask(JsEngineInternal* engine, |
| + const std::string& path, const std::string& content, |
| + V8PersistentNG<v8::Function> callbackFunction) |
| + : jsEngine(engine->shared_from_this()), path(path), content(content), |
| + callbackFunction(callbackFunction) |
| + {} |
| void operator()() |
| { |
| + JsEngineInternal* engine = ToInternal(jsEngine); |
| std::string error; |
| + // Write operation is long-lived. Do not lock engine during it. |
| try |
| { |
| std::shared_ptr<std::iostream> stream(new std::stringstream); |
| *stream << content; |
| - fileSystem->Write(path, stream); |
| + engine->GetFileSystem()->Write(path, stream); |
| } |
| catch (std::exception& e) |
| { |
| @@ -114,34 +114,38 @@ |
| { |
| error = "Unknown error while writing to " + path; |
| } |
| - |
| - const JsContext context(jsEngine); |
| - JsValuePtr errorValue = jsEngine->NewValue(error); |
| - JsValueList params; |
| - params.push_back(errorValue); |
| - callback->Call(params); |
| + // Apply the callback function |
| + V8ExecutionScope scope(engine); |
| + auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| + args[0] = engine->ToV8String(error); |
| + engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::move(args)); |
| } |
| - |
| - private: |
| - std::string path; |
| - std::string content; |
| }; |
| - class MoveTask : public IoTask |
| + class MoveTask |
| { |
| + /** |
| + * Shared pointer keeps engine in existence for task thread. |
| + */ |
| + JsEnginePtr jsEngine; |
| + std::string fromPath; |
| + std::string toPath; |
| + V8PersistentNG<v8::Function> callbackFunction; |
| + |
| public: |
| - MoveTask(JsEnginePtr jsEngine, JsValuePtr callback, |
| - const std::string& fromPath, const std::string& toPath) |
| - : IoTask(jsEngine, callback), fromPath(fromPath), toPath(toPath) |
| - { |
| - } |
| + MoveTask(JsEngineInternal* engine, const std::string& fromPath, const std::string& toPath, |
| + V8PersistentNG<v8::Function> callbackFunction) |
| + : jsEngine(engine->shared_from_this()), fromPath(fromPath), toPath(toPath), |
| + callbackFunction(callbackFunction) |
| + {} |
| void operator()() |
| { |
| + JsEngineInternal* engine(ToInternal(jsEngine)); |
| std::string error; |
| try |
| { |
| - fileSystem->Move(fromPath, toPath); |
| + engine->GetFileSystem()->Move(fromPath, toPath); |
| } |
| catch (std::exception& e) |
| { |
| @@ -151,34 +155,36 @@ |
| { |
| error = "Unknown error while moving " + fromPath + " to " + toPath; |
| } |
| - |
| - const JsContext context(jsEngine); |
| - JsValuePtr errorValue = jsEngine->NewValue(error); |
| - JsValueList params; |
| - params.push_back(errorValue); |
| - callback->Call(params); |
| + V8ExecutionScope scope(engine); |
| + auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| + args[0] = engine->ToV8String(error); |
| + engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::move(args)); |
| } |
| - |
| - private: |
| - std::string fromPath; |
| - std::string toPath; |
| }; |
| - class RemoveTask : public IoTask |
| + class RemoveTask |
| { |
| + /** |
| + * Shared pointer keeps engine in existence for task thread. |
| + */ |
| + JsEnginePtr jsEngine; |
| + std::string path; |
| + V8PersistentNG<v8::Function> callbackFunction; |
| + |
| public: |
| - RemoveTask(JsEnginePtr jsEngine, JsValuePtr callback, |
| - const std::string& path) |
| - : IoTask(jsEngine, callback), path(path) |
| - { |
| - } |
| + RemoveTask(JsEngineInternal *engine, const std::string& path, |
| + V8PersistentNG<v8::Function> callbackFunction) |
| + : jsEngine(engine->shared_from_this()), path(path), |
| + callbackFunction(callbackFunction) |
| + {} |
| void operator()() |
| { |
| + JsEngineInternal* engine(ToInternal(jsEngine)); |
| std::string error; |
| try |
| { |
| - fileSystem->Remove(path); |
| + engine->GetFileSystem()->Remove(path); |
| } |
| catch (std::exception& e) |
| { |
| @@ -188,35 +194,37 @@ |
| { |
| error = "Unknown error while removing " + path; |
| } |
| - |
| - const JsContext context(jsEngine); |
| - JsValuePtr errorValue = jsEngine->NewValue(error); |
| - JsValueList params; |
| - params.push_back(errorValue); |
| - callback->Call(params); |
| + V8ExecutionScope scope(engine); |
| + auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| + args[0] = engine->ToV8String(error); |
| + engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::move(args)); |
| } |
| - |
| - private: |
| - std::string path; |
| }; |
| + class StatTask |
| + { |
| + /** |
| + * Shared pointer keeps engine in existence for task thread. |
| + */ |
| + JsEnginePtr jsEngine; |
| + std::string path; |
| + V8PersistentNG<v8::Function> callbackFunction; |
| - class StatTask : public IoTask |
| - { |
| public: |
| - StatTask(JsEnginePtr jsEngine, JsValuePtr callback, |
| - const std::string& path) |
| - : IoTask(jsEngine, callback), path(path) |
| - { |
| - } |
| + StatTask(JsEngineInternal* engine, const std::string& path, |
| + V8PersistentNG<v8::Function> callbackFunction) |
| + : jsEngine(engine->shared_from_this()), path(path), |
| + callbackFunction(callbackFunction) |
| + {} |
| void operator()() |
| { |
| + JsEngineInternal* engine(ToInternal(jsEngine)); |
| std::string error; |
| FileSystem::StatResult statResult; |
| try |
| { |
| - statResult = fileSystem->Stat(path); |
| + statResult = engine->GetFileSystem()->Stat(path); |
| } |
| catch (std::exception& e) |
| { |
| @@ -226,139 +234,221 @@ |
| { |
| error = "Unknown error while calling stat on " + path; |
| } |
| - |
| - const JsContext context(jsEngine); |
| - JsValuePtr result = jsEngine->NewObject(); |
| - result->SetProperty("exists", statResult.exists); |
| - result->SetProperty("isFile", statResult.isFile); |
| - result->SetProperty("isDirectory", statResult.isDirectory); |
| - result->SetProperty("lastModified", statResult.lastModified); |
| - result->SetProperty("error", error); |
| - |
| - JsValueList params; |
| - params.push_back(result); |
| - callback->Call(params); |
| + V8ExecutionScope scope(engine); |
| + auto callbackArgument(v8::Object::New()); |
| + callbackArgument->Set(engine->ToV8String("exists"), v8::Boolean::New(statResult.exists)); |
| + callbackArgument->Set(engine->ToV8String("isFile"), v8::Boolean::New(statResult.isFile)); |
| + callbackArgument->Set(engine->ToV8String("isDirectory"), v8::Boolean::New(statResult.isDirectory)); |
| + callbackArgument->Set(engine->ToV8String("lastModified"), v8::Number::New(statResult.lastModified)); |
| + callbackArgument->Set(engine->ToV8String("error"), engine->ToV8String(error)); |
| + auto args = AllocatedArray<v8::Local<v8::Value>>(1); |
| + args[0] = callbackArgument; |
| + engine->ApplyFunction(callbackFunction.Get(engine->GetIsolate()), std::move(args)); |
| } |
| - |
| - private: |
| - std::string path; |
| }; |
| - |
| - v8::Handle<v8::Value> ReadCallback(const v8::Arguments& arguments) |
| - { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 2) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "_fileSystem.read requires 2 parameters")); |
| - if (!converted[1]->IsFunction()) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "Second argument to _fileSystem.read must be a function")); |
| - const auto readTask = std::make_shared<ReadTask>(jsEngine, converted[1], |
| - converted[0]->AsString()); |
| - jsEngine->Schedule(AdblockPlus::MakeHeapFunction(readTask), AdblockPlus::ImmediateSingleUseThread); |
| - return v8::Undefined(); |
| - } |
| - |
| - v8::Handle<v8::Value> WriteCallback(const v8::Arguments& arguments) |
| - { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 3) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "_fileSystem.write requires 3 parameters")); |
| - if (!converted[2]->IsFunction()) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "Third argument to _fileSystem.write must be a function")); |
| - const auto writeTask = std::make_shared<WriteTask>(jsEngine, converted[2], |
| - converted[0]->AsString(), converted[1]->AsString()); |
| - jsEngine->Schedule(AdblockPlus::MakeHeapFunction(writeTask), AdblockPlus::ImmediateSingleUseThread); |
| - return v8::Undefined(); |
| - } |
| - |
| - v8::Handle<v8::Value> MoveCallback(const v8::Arguments& arguments) |
| - { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 3) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "_fileSystem.move requires 3 parameters")); |
| - if (!converted[2]->IsFunction()) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "Third argument to _fileSystem.move must be a function")); |
| - const auto moveTask = std::make_shared<MoveTask>(jsEngine, converted[2], |
| - converted[0]->AsString(), converted[1]->AsString()); |
| - jsEngine->Schedule(AdblockPlus::MakeHeapFunction(moveTask), AdblockPlus::ImmediateSingleUseThread); |
| - return v8::Undefined(); |
| - } |
| - |
| - v8::Handle<v8::Value> RemoveCallback(const v8::Arguments& arguments) |
| - { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 2) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "_fileSystem.remove requires 2 parameters")); |
| - if (!converted[1]->IsFunction()) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "Second argument to _fileSystem.remove must be a function")); |
| - const auto removeTask = std::make_shared<RemoveTask>(jsEngine, converted[1], |
| - converted[0]->AsString()); |
| - jsEngine->Schedule(AdblockPlus::MakeHeapFunction(removeTask), AdblockPlus::ImmediateSingleUseThread); |
| - return v8::Undefined(); |
| - } |
| - |
| - v8::Handle<v8::Value> StatCallback(const v8::Arguments& arguments) |
| - { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 2) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "_fileSystem.stat requires 2 parameters")); |
| - if (!converted[1]->IsFunction()) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "Second argument to _fileSystem.stat must be a function")); |
| - const auto statTask = std::make_shared<StatTask>(jsEngine, converted[1], |
| - converted[0]->AsString()); |
| - jsEngine->Schedule(AdblockPlus::MakeHeapFunction(statTask), AdblockPlus::ImmediateSingleUseThread); |
| - return v8::Undefined(); |
| - } |
| - |
| - v8::Handle<v8::Value> ResolveCallback(const v8::Arguments& arguments) |
| - { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 1) |
| - return v8::ThrowException(Utils::ToV8String(isolate, |
| - "_fileSystem.resolve requires 1 parameter")); |
| - |
| - std::string resolved = jsEngine->GetFileSystem()->Resolve(converted[0]->AsString()); |
| - |
| - return Utils::ToV8String(isolate, resolved); |
| - } |
| - |
| } |
| - |
| -JsValuePtr FileSystemJsObject::Setup(JsEnginePtr jsEngine, JsValuePtr obj) |
| +v8::Handle<v8::Value> ReadCallback(const v8::Arguments& arguments) |
| { |
| - obj->SetProperty("read", jsEngine->NewCallback(::ReadCallback)); |
| - obj->SetProperty("write", jsEngine->NewCallback(::WriteCallback)); |
| - obj->SetProperty("move", jsEngine->NewCallback(::MoveCallback)); |
| - obj->SetProperty("remove", jsEngine->NewCallback(::RemoveCallback)); |
| - obj->SetProperty("stat", jsEngine->NewCallback(::StatCallback)); |
| - obj->SetProperty("resolve", jsEngine->NewCallback(::ResolveCallback)); |
| - return obj; |
| + auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| + std::shared_ptr<ReadTask> readTask; |
| + try |
| + { |
| + if (arguments.Length() != 2) |
| + { |
| + throw std::runtime_error("_fileSystem.read requires 2 parameters"); |
| + } |
| + bool argumentIsString; |
| + std::string firstArgument; |
| + std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("First argument to _fileSystem.read must be a string"); |
| + } |
| + if (!arguments[1]->IsFunction()) |
| + { |
| + throw std::runtime_error("Second argument to _fileSystem.read must be a function"); |
| + } |
| + readTask = std::make_shared<ReadTask>(engine, firstArgument, |
| + V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::Cast(arguments[1]))); |
| + } |
| + catch (const std::exception& e) |
| + { |
| + return v8::ThrowException(engine->ToV8String(e.what())); |
| + } |
| + // Run the task |
| + engine->Schedule(AdblockPlus::MakeHeapFunction(readTask), AdblockPlus::ImmediateSingleUseThread); |
| + return v8::Undefined(); |
| } |
| + |
| +v8::Handle<v8::Value> WriteCallback(const v8::Arguments& arguments) |
| +{ |
| + auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| + std::shared_ptr<WriteTask> writeTask; |
| + try |
| + { |
| + v8::Isolate* isolate = arguments.GetIsolate(); |
| + |
| + if (arguments.Length() != 3) |
| + { |
| + throw std::exception("_fileSystem.write requires 3 parameters"); |
| + } |
| + bool argumentIsString; |
| + std::string firstArgument; |
| + std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("First argument to _fileSystem.write must be a string"); |
| + } |
| + std::string secondArgument; |
| + std::tie(argumentIsString, secondArgument) = ConvertString(arguments[1]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("Second argument to _fileSystem.write must be a string"); |
| + } |
| + if (!arguments[2]->IsFunction()) |
| + { |
| + throw std::runtime_error("Third argument to _fileSystem.write must be a function"); |
| + } |
| + writeTask = std::make_shared<WriteTask>(engine, firstArgument, secondArgument, |
| + V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::Cast(arguments[2]))); |
| + } |
| + catch (const std::exception& e) |
| + { |
| + return v8::ThrowException(engine->ToV8String(e.what())); |
| + } |
| + engine->Schedule(AdblockPlus::MakeHeapFunction(writeTask), AdblockPlus::ImmediateSingleUseThread); |
| + return v8::Undefined(); |
| +} |
| + |
| +v8::Handle<v8::Value> MoveCallback(const v8::Arguments& arguments) |
| +{ |
| + auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| + std::shared_ptr<MoveTask> moveTask; |
| + std::string firstArgument, secondArgument; |
| + try |
| + { |
| + if (arguments.Length() != 3) |
| + { |
| + throw std::runtime_error("_fileSystem.move requires 3 parameters"); |
| + } |
| + bool argumentIsString; |
| + std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("First argument to _fileSystem.write must be a string"); |
| + } |
| + std::tie(argumentIsString, secondArgument) = ConvertString(arguments[1]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("Second argument to _fileSystem.write must be a string"); |
| + } |
| + if (!arguments[2]->IsFunction()) |
| + { |
| + throw std::runtime_error("Third argument to _fileSystem.move must be a function"); |
| + } |
| + } |
| + catch (const std::exception& e) |
| + { |
| + return v8::ThrowException(engine->ToV8String(e.what())); |
| + } |
| + // Run the task |
| + moveTask = std::make_shared<MoveTask>(engine, firstArgument, secondArgument, |
| + V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::Cast(arguments[2]))); |
| + engine->Schedule(AdblockPlus::MakeHeapFunction(moveTask), AdblockPlus::ImmediateSingleUseThread); |
| + return v8::Undefined(); |
| +} |
| + |
| +v8::Handle<v8::Value> RemoveCallback(const v8::Arguments& arguments) |
| +{ |
| + auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| + std::shared_ptr<RemoveTask> removeTask; |
| + std::string firstArgument; |
| + try |
| + { |
| + if (arguments.Length() != 2) |
| + { |
| + throw std::runtime_error("_fileSystem.remove requires 2 parameters"); |
| + } |
| + bool argumentIsString; |
| + std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("First argument to _fileSystem.remove must be a string"); |
| + } |
| + if (!arguments[1]->IsFunction()) |
| + { |
| + throw std::runtime_error("Second argument to _fileSystem.remove must be a function"); |
| + } |
| + } |
| + catch (const std::exception& e) |
| + { |
| + return v8::ThrowException(engine->ToV8String(e.what())); |
| + } |
| + // Run the task |
| + removeTask = std::make_shared<RemoveTask>(engine, firstArgument, |
| + V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::Cast(arguments[1]))); |
| + engine->Schedule(AdblockPlus::MakeHeapFunction(removeTask), AdblockPlus::ImmediateSingleUseThread); |
| + return v8::Undefined(); |
| +} |
| + |
| +v8::Handle<v8::Value> StatCallback(const v8::Arguments& arguments) |
| +{ |
| + auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| + std::shared_ptr<StatTask> statTask; |
| + std::string firstArgument; |
| + try |
| + { |
| + if (arguments.Length() != 2) |
| + { |
| + throw std::runtime_error("_fileSystem.stat requires 2 parameters"); |
| + } |
| + bool argumentIsString; |
| + std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("First argument to _fileSystem.stat must be a string"); |
| + } |
| + if (!arguments[1]->IsFunction()) |
| + { |
| + throw std::runtime_error("Second argument to _fileSystem.stat must be a function"); |
| + } |
| + } |
| + catch (const std::exception& e) |
| + { |
| + return v8::ThrowException(engine->ToV8String(e.what())); |
| + } |
| + // Run the task |
| + statTask = std::make_shared<StatTask>(engine, firstArgument, |
| + V8PersistentNG<v8::Function>(engine->GetIsolate(), v8::Local<v8::Function>::Cast(arguments[1]))); |
| + engine->Schedule(AdblockPlus::MakeHeapFunction(statTask), AdblockPlus::ImmediateSingleUseThread); |
| + return v8::Undefined(); |
| +} |
| + |
| +v8::Handle<v8::Value> ResolveCallback(const v8::Arguments& arguments) |
| +{ |
| + auto engine(JsEngineInternal::ExtractEngine(arguments)); |
| + std::string firstArgument; |
| + try |
| + { |
| + if (arguments.Length() != 1) |
| + { |
| + throw std::runtime_error("_fileSystem.resolve requires 1 parameter"); |
| + } |
| + bool argumentIsString; |
| + std::tie(argumentIsString, firstArgument) = ConvertString(arguments[0]); |
| + if (!argumentIsString) |
| + { |
| + throw std::runtime_error("First argument to _fileSystem.write must be a string"); |
| + } |
| + } |
| + catch (const std::exception& e) |
| + { |
| + return v8::ThrowException(engine->ToV8String(e.what())); |
| + } |
| + /* |
| + * Make sure to perform long-lived file system operation with engine unlocked. |
| + */ |
| + std::string resolved = engine->GetFileSystem()->Resolve(firstArgument); |
| + return engine->ToV8String(resolved); |
| +} |