Index: src/FileSystemJsObject.cpp |
diff --git a/src/FileSystemJsObject.cpp b/src/FileSystemJsObject.cpp |
index 37e1627c7c1ab0797add282ada968c940f04e1af..fd17fb5432280f66b5a055cd0e164c9f8b65de97 100644 |
--- a/src/FileSystemJsObject.cpp |
+++ b/src/FileSystemJsObject.cpp |
@@ -24,6 +24,7 @@ |
#include "FileSystemJsObject.h" |
#include "JsContext.h" |
#include "Utils.h" |
+#include "JsError.h" |
#include <AdblockPlus/Platform.h> |
using namespace AdblockPlus; |
@@ -63,6 +64,86 @@ namespace |
}); |
} |
+ 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) |
+ { |
+ 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; |
+ jsEngine->GetPlatform().GetFileSystem().Read(converted[0].AsString(), |
+ [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()) |
+ { |
+ 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; |
+ |
+ 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()) |
+ { |
+ jsValues[1].Call(jsEngine->NewValue(JsError::ExceptionToString(tryCatch.Exception(), tryCatch.Message()))); |
+ return; |
+ } |
+ stringBegin = SkipEndOfLine(stringEnd, contentEnd); |
+ } while (stringBegin != contentEnd); |
+ jsValues[1].Call(); |
+ }); |
+ } |
+ |
void WriteCallback(const v8::FunctionCallbackInfo<v8::Value>& arguments) |
{ |
AdblockPlus::JsEnginePtr jsEngine = AdblockPlus::JsEngine::FromArguments(arguments); |
@@ -198,6 +279,7 @@ namespace |
JsValue& FileSystemJsObject::Setup(JsEngine& jsEngine, JsValue& obj) |
{ |
obj.SetProperty("read", jsEngine.NewCallback(::ReadCallback)); |
+ obj.SetProperty("readFromFile", jsEngine.NewCallback(::ReadFromFileCallback)); |
obj.SetProperty("write", jsEngine.NewCallback(::WriteCallback)); |
obj.SetProperty("move", jsEngine.NewCallback(::MoveCallback)); |
obj.SetProperty("remove", jsEngine.NewCallback(::RemoveCallback)); |