Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): support onerror for js #3471

Merged
merged 3 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 4 additions & 18 deletions driver/js/include/driver/scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,24 +275,7 @@ class Scope : public std::enable_shared_from_this<Scope> {

inline void SetUriLoader(std::weak_ptr<UriLoader> loader) {
loader_ = loader;
auto the_loader = loader_.lock();
if (the_loader) {
the_loader->SetRequestTimePerformanceCallback([WEAK_THIS](const string_view& uri, const TimePoint& start, const TimePoint& end) {
DEFINE_AND_CHECK_SELF(Scope)
auto runner = self->GetTaskRunner();
if (runner) {
auto task = [weak_this, uri, start, end]() {
DEFINE_AND_CHECK_SELF(Scope)
auto entry = self->GetPerformance()->PerformanceResource(uri);
if (entry) {
entry->SetLoadSourceStart(start);
entry->SetLoadSourceEnd(end);
}
};
runner->PostTask(std::move(task));
}
});
}
SetCallbackForUriLoader();
}

inline std::weak_ptr<UriLoader> GetUriLoader() { return loader_; }
Expand Down Expand Up @@ -327,6 +310,8 @@ class Scope : public std::enable_shared_from_this<Scope> {
return performance_;
}

void HandleUriLoaderError(const string_view& uri, const int32_t ret_code, const string_view& error_msg);

#ifdef ENABLE_INSPECTOR
inline void SetDevtoolsDataSource(std::shared_ptr<hippy::devtools::DevtoolsDataSource> devtools_data_source) {
devtools_data_source_ = devtools_data_source;
Expand Down Expand Up @@ -472,6 +457,7 @@ class Scope : public std::enable_shared_from_this<Scope> {
friend class Engine;
void BindModule();
void Bootstrap();
void SetCallbackForUriLoader();

private:
std::weak_ptr<Engine> engine_;
Expand Down
3 changes: 2 additions & 1 deletion driver/js/include/driver/vm/js_vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ class VM {
return uncaught_exception_callback_;
}

static void HandleUncaughtException(const std::shared_ptr<Ctx>& ctx, const std::shared_ptr<CtxValue>& exception);
static void HandleException(const std::shared_ptr<Ctx>& ctx, const string_view& event_name, const std::shared_ptr<CtxValue>& exception);

virtual std::shared_ptr<CtxValue> ParseJson(const std::shared_ptr<Ctx>& ctx, const string_view& json) = 0;
virtual std::shared_ptr<Ctx> CreateContext() = 0;
private:
Expand Down
40 changes: 38 additions & 2 deletions driver/js/lib/global/Others.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ global.__GLOBAL__ = {
globalEventHandle: {},
};

class ErrorEvent {
constructor(message, filename, lineno, colno, error) {
this.message = message;
this.filename = filename;
this.lineno = lineno;
this.colno = colno;
this.error = error;
}
}

/**
* Register the Hippy app entry function, the native will trigger an event to execute the function
* and start the app.
Expand Down Expand Up @@ -99,15 +109,38 @@ function emit(eventName, ...args) {
if (typeof eventName !== 'string') {
throw new TypeError('Hippy.emit() only accept a string as event name');
}

let isErr = eventName === 'error';
let errObj = new Error();
if (isErr) {
let arr = args[0];
if (!(arr instanceof Array)) {
throw new TypeError('Hippy.emit() error event, args0 must be array');
}
if (arr.length !== 5) {
throw new TypeError('Hippy.emit() error event, args0 length must be 5');
}
errObj.message = JSON.stringify(arr[4]);
if (Hippy.onerror) {
Hippy.onerror(arr[0], arr[1], arr[2], arr[3], errObj);
}
}

const eventListeners = __GLOBAL__.globalEventHandle[eventName];
if (!eventListeners) {
if (eventName === 'uncaughtException' && args[0]) {
if (args[0]) {
console.error(args[0].toString());
}
return;
}
try {
eventListeners.forEach(listener => listener(...args));
if (isErr) {
let arr = args[0];
let event = new ErrorEvent(arr[0], arr[1], arr[2], arr[3], errObj);
eventListeners.forEach(listener => listener(event));
} else {
eventListeners.forEach(listener => listener(...args));
}
} catch (err) {
/* eslint-disable-next-line no-console */
console.error(err);
Expand All @@ -122,3 +155,6 @@ Hippy.register = {
Hippy.on = on;
Hippy.off = off;
Hippy.emit = emit;
Hippy.addEventListener = on;
Hippy.removeEventListener = off;
Hippy.onerror = undefined;
6 changes: 3 additions & 3 deletions driver/js/lib/modules/ExceptionHandle.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
* limitations under the License.
*/

(function exceptionHandler(eventName, err) {
(function exceptionHandler(eventName, exception) {
if (global.Hippy) {
global.Hippy.emit('uncaughtException', err);
global.Hippy.emit(eventName, exception);
} else {
/* eslint-disable-next-line no-console */
console.error(eventName, err);
console.error(eventName, exception);
}
});
2 changes: 1 addition & 1 deletion driver/js/src/js_driver_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ void AsyncInitializeEngine(const std::shared_ptr<Engine>& engine,
auto scope = scope_wrapper->scope.lock();
FOOTSTONE_CHECK(scope);
auto exception = info[0];
V8VM::HandleUncaughtException(scope->GetContext(), exception);
V8VM::HandleException(scope->GetContext(), "uncaughtException", exception);
auto engine = scope->GetEngine().lock();
FOOTSTONE_CHECK(engine);
auto callback = engine->GetVM()->GetUncaughtExceptionCallback();
Expand Down
40 changes: 40 additions & 0 deletions driver/js/src/scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -599,5 +599,45 @@ void Scope::UnloadInstance(const std::shared_ptr<HippyValue>& value) {
}
}

void Scope::SetCallbackForUriLoader() {
auto the_loader = loader_.lock();
if (the_loader) {
the_loader->SetRequestResultCallback([WEAK_THIS](const string_view& uri,
const TimePoint& start, const TimePoint& end,
const int32_t ret_code, const string_view& error_msg) {
DEFINE_AND_CHECK_SELF(Scope)
auto runner = self->GetTaskRunner();
if (runner) {
auto task = [weak_this, uri, start, end, ret_code, error_msg]() {
DEFINE_AND_CHECK_SELF(Scope)
auto entry = self->GetPerformance()->PerformanceResource(uri);
if (entry) {
entry->SetLoadSourceStart(start);
entry->SetLoadSourceEnd(end);
}
if (ret_code != 0) {
self->HandleUriLoaderError(uri, ret_code, error_msg);
}
};
runner->PostTask(std::move(task));
}
});
}
}

void Scope::HandleUriLoaderError(const string_view& uri, const int32_t ret_code, const string_view& error_msg) {
std::unordered_map<string_view, std::shared_ptr<CtxValue>> error_map;
error_map["code"] = context_->CreateNumber(static_cast<double>(ret_code));
error_map["message"] = context_->CreateString(error_msg);
auto event = context_->CreateString("vfs error");
auto source = context_->CreateString(uri);
auto lineno = context_->CreateNumber(0);
auto colno = context_->CreateNumber(0);
auto error = context_->CreateObject(error_map);
std::shared_ptr<CtxValue> arr[5] = {event, source, lineno, colno, error};
auto exception = context_->CreateArray(5, arr);
VM::HandleException(context_, "error", exception);
}

}
}
17 changes: 8 additions & 9 deletions driver/js/src/vm/js_vm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,29 @@ namespace hippy {
inline namespace driver {
inline namespace vm {

constexpr char kEventName[] = "uncaughtException";
constexpr char kErrorHandlerJSName[] = "ExceptionHandle.js";
constexpr char kHippyErrorHandlerName[] = "HippyExceptionHandler";
constexpr char kExceptionHandlerJSName[] = "ExceptionHandle.js";
constexpr char kHippyExceptionHandlerName[] = "HippyExceptionHandler";

using Ctx = hippy::Ctx;
using CtxValue = hippy::CtxValue;

void VM::HandleUncaughtException(const std::shared_ptr<Ctx>& ctx,
const std::shared_ptr<CtxValue>& exception) {
void VM::HandleException(const std::shared_ptr<Ctx>& ctx,
const string_view& event_name,
const std::shared_ptr<CtxValue>& exception) {
auto global_object = ctx->GetGlobalObject();
string_view error_handle_name(kHippyErrorHandlerName);
string_view error_handle_name(kHippyExceptionHandlerName);
auto error_handle_key = ctx->CreateString(error_handle_name);
auto exception_handler = ctx->GetProperty(global_object, error_handle_key);
if (!ctx->IsFunction(exception_handler)) {
const auto& source_code = hippy::GetNativeSourceCode(kErrorHandlerJSName);
const auto& source_code = hippy::GetNativeSourceCode(kExceptionHandlerJSName);
FOOTSTONE_DCHECK(source_code.data_ && source_code.length_);
string_view str_view(source_code.data_, source_code.length_);
exception_handler = ctx->RunScript(str_view, error_handle_name);
ctx->SetProperty(global_object, error_handle_key, exception_handler);
}

std::shared_ptr<CtxValue> argv[2];
argv[0] = ctx->CreateString(kEventName);
argv[0] = ctx->CreateString(event_name);
argv[1] = exception;

auto try_catch = CreateTryCatchScope(true, ctx);
Expand All @@ -63,7 +63,6 @@ void VM::HandleUncaughtException(const std::shared_ptr<Ctx>& ctx,
}
}


}
}
}
Loading
Loading