| Index: src/FileSystemJsObject.cpp |
| diff --git a/src/FileSystemJsObject.cpp b/src/FileSystemJsObject.cpp |
| index 6226fa0c58c4a41c09c755d33d0904940a637150..4225b2e6217e4108116dfee5aa3c6043883b6a81 100644 |
| --- a/src/FileSystemJsObject.cpp |
| +++ b/src/FileSystemJsObject.cpp |
| @@ -32,127 +32,178 @@ using AdblockPlus::Utils::ThrowExceptionInJS; |
| namespace |
| { |
| - void ReadCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
| + namespace ReadCallback |
|
sergei
2018/03/23 11:27:19
the changes here are:
- create the namespace `Read
|
| { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 2) |
| - return ThrowExceptionInJS(isolate, "_fileSystem.read requires 2 parameters"); |
| - if (!converted[1].IsFunction()) |
| - return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.read must be a function"); |
| - |
| - JsValueList values; |
| - values.push_back(converted[1]); |
| - auto weakCallback = jsEngine->StoreJsValues(values); |
| - std::weak_ptr<JsEngine> weakJsEngine = jsEngine; |
| - auto fileName = converted[0].AsString(); |
| - jsEngine->GetPlatform().WithFileSystem( |
| - [weakJsEngine, weakCallback, fileName](IFileSystem& fileSystem) |
| + struct WeakData |
| + { |
| + public: |
| + WeakData(const JsEnginePtr& jsEngine, |
| + JsEngine::JsWeakValuesID weakResolveCallback, |
| + JsEngine::JsWeakValuesID weakRejectCallback) |
| + : weakJsEngine(jsEngine) |
| + , weakResolveCallback(weakResolveCallback) |
| + , weakRejectCallback(weakRejectCallback) |
| { |
| - fileSystem.Read(fileName, |
| - [weakJsEngine, weakCallback] |
| - (IFileSystem::IOBuffer&& content, const std::string& error) |
| - { |
| - auto jsEngine = weakJsEngine.lock(); |
| - if (!jsEngine) |
| - return; |
| - |
| - const JsContext context(*jsEngine); |
| - auto result = jsEngine->NewObject(); |
| - result.SetStringBufferProperty("content", std::move(content)); |
| - if (!error.empty()) |
| - result.SetProperty("error", error); |
| - jsEngine->TakeJsValues(weakCallback)[0].Call(result); |
| - }); |
| - }); |
| - } |
| - |
| - inline bool IsEndOfLine(char c) |
| - { |
| - return c == 10 || c == 13; |
| - } |
| - |
| - inline StringBuffer::const_iterator SkipEndOfLine(StringBuffer::const_iterator ii, StringBuffer::const_iterator end) |
| - { |
| - while (ii != end && IsEndOfLine(*ii)) |
| - ++ii; |
| - return ii; |
| - } |
| - |
| - inline StringBuffer::const_iterator AdvanceToEndOfLine(StringBuffer::const_iterator ii, StringBuffer::const_iterator end) |
| - { |
| - while (ii != end && !IsEndOfLine(*ii)) |
| - ++ii; |
| - return ii; |
| - } |
| - |
| - void ReadFromFileCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
| + } |
| + virtual ~WeakData() |
| + { |
| + auto jsEngine = weakJsEngine.lock(); |
| + if (!jsEngine) |
| + return; |
| + jsEngine->TakeJsValues(weakResolveCallback); |
| + jsEngine->TakeJsValues(weakRejectCallback); |
| + } |
| + std::weak_ptr<JsEngine> weakJsEngine; |
| + JsEngine::JsWeakValuesID weakResolveCallback; |
| + JsEngine::JsWeakValuesID weakRejectCallback; |
| + }; |
| + |
| + static void V8Callback(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
| + { |
| + AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| + AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| + |
| + v8::Isolate* isolate = arguments.GetIsolate(); |
| + if (converted.size() != 3) |
| + return ThrowExceptionInJS(isolate, "_fileSystem.read requires 3 parameters"); |
| + if (!converted[1].IsFunction()) |
| + return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.read must be a function"); |
| + if (!converted[2].IsFunction()) |
| + return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.read must be a function"); |
| + |
| + auto weakResolveCallback = jsEngine->StoreJsValues({converted[1]}); |
| + auto weakRejectCallback = jsEngine->StoreJsValues({converted[2]}); |
| + auto weakData = std::make_shared<WeakData>(jsEngine, weakResolveCallback, weakRejectCallback); |
| + auto fileName = converted[0].AsString(); |
| + jsEngine->GetPlatform().WithFileSystem( |
| + [weakData, fileName](IFileSystem& fileSystem) |
| + { |
| + fileSystem.Read(fileName, [weakData](IFileSystem::IOBuffer&& content) |
| + { |
| + auto jsEngine = weakData->weakJsEngine.lock(); |
| + if (!jsEngine) |
| + return; |
| + const JsContext context(*jsEngine); |
| + auto result = jsEngine->NewObject(); |
| + result.SetStringBufferProperty("content", content); |
| + jsEngine->GetJsValues(weakData->weakResolveCallback)[0].Call(result); |
| + }, |
| + [weakData](const std::string& error) |
| + { |
| + if (error.empty()) |
| + return; |
| + auto jsEngine = weakData->weakJsEngine.lock(); |
| + if (!jsEngine) |
| + return; |
| + const JsContext context(*jsEngine); |
| + jsEngine->GetJsValues(weakData->weakRejectCallback)[0].Call(jsEngine->NewValue(error)); |
| + }); |
| + }); |
| + } // V8Callback |
| + } // namespace ReadCallback |
| + |
| + namespace ReadFromFileCallback |
|
sergei
2018/03/23 11:27:19
the changes here are:
- create the namespace `Read
|
| { |
| - AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| - AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| - |
| - v8::Isolate* isolate = arguments.GetIsolate(); |
| - if (converted.size() != 3) |
| - return ThrowExceptionInJS(isolate, "_fileSystem.readFromFile requires 3 parameters"); |
| - if (!converted[1].IsFunction()) |
| - return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.readFromFile must be a function (listener callback)"); |
| - if (!converted[2].IsFunction()) |
| - return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.readFromFile must be a function (done callback)"); |
| - |
| - JsValueList values; |
| - values.push_back(converted[1]); |
| - values.push_back(converted[2]); |
| - auto weakCallback = jsEngine->StoreJsValues(values); |
| - std::weak_ptr<JsEngine> weakJsEngine = jsEngine; |
| - auto fileName = converted[0].AsString(); |
| - jsEngine->GetPlatform().WithFileSystem( |
| - [weakJsEngine, weakCallback, fileName](IFileSystem& fileSystem) |
| + inline bool IsEndOfLine(char c) |
| + { |
| + return c == 10 || c == 13; |
| + } |
| + |
| + inline StringBuffer::const_iterator SkipEndOfLine(StringBuffer::const_iterator ii, StringBuffer::const_iterator end) |
| + { |
| + while (ii != end && IsEndOfLine(*ii)) |
| + ++ii; |
| + return ii; |
| + } |
| + |
| + inline StringBuffer::const_iterator AdvanceToEndOfLine(StringBuffer::const_iterator ii, StringBuffer::const_iterator end) |
| + { |
| + while (ii != end && !IsEndOfLine(*ii)) |
| + ++ii; |
| + return ii; |
| + } |
| + |
| + struct WeakData : ReadCallback::WeakData |
| + { |
| + public: |
| + WeakData(const JsEnginePtr& jsEngine, |
| + JsEngine::JsWeakValuesID weakResolveCallback, |
| + JsEngine::JsWeakValuesID weakRejectCallback, |
| + JsEngine::JsWeakValuesID weakProcessFunc) |
| + : ReadCallback::WeakData(jsEngine, weakResolveCallback, weakRejectCallback) |
| + , weakProcessFunc(weakProcessFunc) |
| { |
| - fileSystem.Read(fileName, |
| - [weakJsEngine, weakCallback] |
| - (IFileSystem::IOBuffer&& content, const std::string& error) |
| - { |
| - auto jsEngine = weakJsEngine.lock(); |
| - if (!jsEngine) |
| - return; |
| - |
| - const JsContext context(*jsEngine); |
| - |
| - auto jsValues = jsEngine->TakeJsValues(weakCallback); |
| - if (!error.empty()) |
| + } |
| + ~WeakData() |
| + { |
| + auto jsEngine = weakJsEngine.lock(); |
| + if (!jsEngine) |
| + return; |
| + jsEngine->TakeJsValues(weakProcessFunc); |
| + } |
| + JsEngine::JsWeakValuesID weakProcessFunc; |
| + }; |
| + |
| + void V8Callback(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
| + { |
| + AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
| + AdblockPlus::JsValueList converted = jsEngine->ConvertArguments(arguments); |
| + |
| + v8::Isolate* isolate = arguments.GetIsolate(); |
| + if (converted.size() != 4) |
| + return ThrowExceptionInJS(isolate, "_fileSystem.readFromFile requires 4 parameters"); |
| + if (!converted[1].IsFunction()) |
| + return ThrowExceptionInJS(isolate, "Second argument to _fileSystem.readFromFile must be a function (listener callback)"); |
| + if (!converted[2].IsFunction()) |
| + return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.readFromFile must be a function (done callback)"); |
| + if (!converted[3].IsFunction()) |
| + return ThrowExceptionInJS(isolate, "Third argument to _fileSystem.readFromFile must be a function (error callback)"); |
| + |
| + auto weakProcessFunc = jsEngine->StoreJsValues({converted[1]}); |
| + auto weakResolveCallback = jsEngine->StoreJsValues({converted[2]}); |
| + auto weakRejectCallback = jsEngine->StoreJsValues({converted[3]}); |
| + auto weakData = std::make_shared<WeakData>(jsEngine, weakResolveCallback, weakRejectCallback, weakProcessFunc); |
| + auto fileName = converted[0].AsString(); |
| + jsEngine->GetPlatform().WithFileSystem([weakData, fileName](IFileSystem& fileSystem) |
| + { |
| + fileSystem.Read(fileName, [weakData](IFileSystem::IOBuffer&& content) |
| { |
| - jsValues[1].Call(jsEngine->NewValue(error)); |
| - return; |
| - } |
| - |
| - auto processFunc = jsValues[0].UnwrapValue().As<v8::Function>(); |
| - |
| - auto globalContext = context.GetV8Context()->Global(); |
| - if (!globalContext->IsObject()) |
| - throw std::runtime_error("`this` pointer has to be an object"); |
| - |
| - const v8::TryCatch tryCatch; |
| + auto jsEngine = weakData->weakJsEngine.lock(); |
| + if (!jsEngine) |
| + return; |
| - const auto contentEnd = content.cend(); |
| - auto stringBegin = SkipEndOfLine(content.begin(), contentEnd); |
| - do |
| - { |
| - auto stringEnd = AdvanceToEndOfLine(stringBegin, contentEnd); |
| - auto jsLine = Utils::StringBufferToV8String(jsEngine->GetIsolate(), StringBuffer(stringBegin, stringEnd)).As<v8::Value>(); |
| - processFunc->Call(globalContext, 1, &jsLine); |
| - if (tryCatch.HasCaught()) |
| + const JsContext context(*jsEngine); |
| + auto jsValues = jsEngine->GetJsValues(weakData->weakProcessFunc); |
| + auto processFunc = jsValues[0].UnwrapValue().As<v8::Function>(); |
| + auto globalContext = context.GetV8Context()->Global(); |
| + if (!globalContext->IsObject()) |
| + throw std::runtime_error("`this` pointer has to be an object"); |
| + |
| + const v8::TryCatch tryCatch; |
| + const auto contentEnd = content.cend(); |
| + auto stringBegin = SkipEndOfLine(content.begin(), contentEnd); |
| + do |
| { |
| - jsValues[1].Call(jsEngine->NewValue(JsError::ExceptionToString(tryCatch.Exception(), tryCatch.Message()))); |
| + auto stringEnd = AdvanceToEndOfLine(stringBegin, contentEnd); |
| + auto jsLine = Utils::StringBufferToV8String(jsEngine->GetIsolate(), StringBuffer(stringBegin, stringEnd)).As<v8::Value>(); |
| + processFunc->Call(globalContext, 1, &jsLine); |
| + if (tryCatch.HasCaught()) |
| + throw JsError(tryCatch.Exception(), tryCatch.Message()); |
|
sergei
2018/03/23 11:27:19
Please pay attention to this change. Previously it
|
| + stringBegin = SkipEndOfLine(stringEnd, contentEnd); |
| + } while (stringBegin != contentEnd); |
| + jsEngine->GetJsValues(weakData->weakResolveCallback)[0].Call(); |
| + }, [weakData](const std::string& error) |
| + { |
| + if (error.empty()) |
| return; |
| - } |
| - stringBegin = SkipEndOfLine(stringEnd, contentEnd); |
| - } while (stringBegin != contentEnd); |
| - jsValues[1].Call(); |
| - }); |
| - }); |
| - } |
| + auto jsEngine = weakData->weakJsEngine.lock(); |
| + if (!jsEngine) |
| + return; |
| + jsEngine->GetJsValues(weakData->weakRejectCallback)[0].Call(jsEngine->NewValue(error)); |
| + }); |
| + }); |
| + } // V8Callback |
| + } // namespace ReadFromFileCallback |
| void WriteCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
| { |
| @@ -307,8 +358,8 @@ namespace |
| JsValue& FileSystemJsObject::Setup(JsEngine& jsEngine, JsValue& obj) |
| { |
| - obj.SetProperty("read", jsEngine.NewCallback(::ReadCallback)); |
| - obj.SetProperty("readFromFile", jsEngine.NewCallback(::ReadFromFileCallback)); |
| + obj.SetProperty("read", jsEngine.NewCallback(::ReadCallback::V8Callback)); |
| + obj.SetProperty("readFromFile", jsEngine.NewCallback(::ReadFromFileCallback::V8Callback)); |
| obj.SetProperty("write", jsEngine.NewCallback(::WriteCallback)); |
| obj.SetProperty("move", jsEngine.NewCallback(::MoveCallback)); |
| obj.SetProperty("remove", jsEngine.NewCallback(::RemoveCallback)); |