diff --git a/driver/js/include/driver/scope.h b/driver/js/include/driver/scope.h index bfed62e896b..0daf07568c6 100644 --- a/driver/js/include/driver/scope.h +++ b/driver/js/include/driver/scope.h @@ -166,6 +166,24 @@ class Scope : public std::enable_shared_from_this { inline std::any GetTurbo() { return turbo_; } inline void SetTurbo(std::any turbo) { turbo_ = turbo; } inline std::weak_ptr GetEngine() { return engine_; } + inline std::unique_ptr& GetRegisterMap() { return extra_function_map_; } + + inline bool RegisterExtraCallback(const std::string& key, RegisterFunction func) { + if (!func) { + return false; + } + (*extra_function_map_)[key] = std::move(func); + return true; + } + + inline bool GetExtraCallback(const std::string& key, RegisterFunction& outFunc) const { + auto it = extra_function_map_->find(key); + if (it != extra_function_map_->end()) { + outFunc = it->second; + return true; + } + return false; + } inline std::any GetClassTemplate(const string_view& name) { auto engine = engine_.lock(); @@ -466,6 +484,7 @@ class Scope : public std::enable_shared_from_this { std::any bridge_; std::any turbo_; std::string name_; + std::unique_ptr extra_function_map_; // store some callback functions uint32_t call_ui_function_callback_id_; std::unordered_map> call_ui_function_callback_holder_; std::unordered_map>>> diff --git a/driver/js/src/modules/timer_module.cc b/driver/js/src/modules/timer_module.cc index 771fe2b737e..fb38c6b5b94 100644 --- a/driver/js/src/modules/timer_module.cc +++ b/driver/js/src/modules/timer_module.cc @@ -216,6 +216,15 @@ std::shared_ptr TimerModule::Start( } std::shared_ptr context = scope->GetContext(); context->CallFunction(function, context->GetGlobalObject(), 0, nullptr); + +#if defined(JS_JSC) + // exception check for jsc + RegisterFunction func; + if (scope->GetExtraCallback(kAsyncTaskEndKey, func)) { + func(nullptr); + } +#endif /* defined(JS_JSC) */ + if (!repeat) { timer_map->erase(task_id); } diff --git a/driver/js/src/napi/jsc/jsc_ctx.cc b/driver/js/src/napi/jsc/jsc_ctx.cc index da7bdd15c6e..21669d0905f 100644 --- a/driver/js/src/napi/jsc/jsc_ctx.cc +++ b/driver/js/src/napi/jsc/jsc_ctx.cc @@ -359,7 +359,6 @@ std::shared_ptr JSCCtx::DefineClass(const string_view& name, JSObjectCallAsFunction(context_, define_property, object, 3, values, &exception); if (exception) { SetException(std::make_shared(context_, exception)); - FOOTSTONE_LOG(ERROR) << GetExceptionMessage(exception_); return nullptr; } } @@ -895,7 +894,6 @@ std::shared_ptr JSCCtx::CallFunction(const std::shared_ptr& auto function_object = JSValueToObject(context_, function_value->value_, &exception); if (exception) { SetException(std::make_shared(context_, exception)); - FOOTSTONE_LOG(ERROR) << GetExceptionMessage(exception_); return nullptr; } @@ -903,7 +901,6 @@ std::shared_ptr JSCCtx::CallFunction(const std::shared_ptr& auto receiver_object = JSValueToObject(context_, receiver_value->value_, &exception); if (exception) { SetException(std::make_shared(context_, exception)); - FOOTSTONE_LOG(ERROR) << GetExceptionMessage(exception_); return nullptr; } @@ -911,7 +908,6 @@ std::shared_ptr JSCCtx::CallFunction(const std::shared_ptr& auto ret_value_ref = JSObjectCallAsFunction(context_, function_object, receiver_object, 0, nullptr, &exception); if (exception) { SetException(std::make_shared(context_, exception)); - FOOTSTONE_LOG(ERROR) << GetExceptionMessage(exception_); return nullptr; } return std::make_shared(context_, ret_value_ref); @@ -926,7 +922,6 @@ std::shared_ptr JSCCtx::CallFunction(const std::shared_ptr& auto ret_value_ref = JSObjectCallAsFunction(context_, function_object, receiver_object, argc, values, &exception); if (exception) { SetException(std::make_shared(context_, exception)); - FOOTSTONE_LOG(ERROR) << GetExceptionMessage(exception_); return nullptr; } @@ -939,7 +934,7 @@ std::shared_ptr JSCCtx::CallFunction(const std::shared_ptr& string_view JSCCtx::GetExceptionMessage(const std::shared_ptr& exception) { if (!exception) { - return string_view(); + return string_view(""); } std::shared_ptr msg_obj = CopyNamedProperty(exception, string_view(kMessageStr, ARRAY_SIZE(kMessageStr) - 1)); @@ -1142,7 +1137,6 @@ std::shared_ptr JSCCtx::RunScript(const string_view& data, if (exception) { SetException(std::make_shared(context_, exception)); - FOOTSTONE_LOG(ERROR) << GetExceptionMessage(exception_); return nullptr; } diff --git a/driver/js/src/scope.cc b/driver/js/src/scope.cc index 56a97e40e76..8880775e5af 100644 --- a/driver/js/src/scope.cc +++ b/driver/js/src/scope.cc @@ -126,6 +126,7 @@ Scope::Scope(std::weak_ptr engine, context_(nullptr), name_(std::move(name)), call_ui_function_callback_id_(0), + extra_function_map_(std::make_unique()), performance_(std::make_shared()) {} Scope::~Scope() { diff --git a/framework/ios/base/executors/HippyJSExecutor.mm b/framework/ios/base/executors/HippyJSExecutor.mm index c01e4fad905..c6aed485dca 100644 --- a/framework/ios/base/executors/HippyJSExecutor.mm +++ b/framework/ios/base/executors/HippyJSExecutor.mm @@ -75,7 +75,7 @@ constexpr char kGlobalKey[] = "global"; constexpr char kHippyKey[] = "Hippy"; static NSString * const kHippyNativeGlobalKey = @"__HIPPYNATIVEGLOBAL__"; - +static const char * kHippyExceptionEventName = "uncaughtException"; @interface HippyJSExecutor () { @@ -102,8 +102,18 @@ - (void)setup { const char *pName = [self.enginekey UTF8String] ?: ""; auto scope = engine->GetEngine()->CreateScope(pName); + __weak __typeof(self)weakSelf = self; + hippy::base::RegisterFunction taskEndCB = [weakSelf](void *) { + @autoreleasepool { + HippyJSExecutor *strongSelf = weakSelf; + if (strongSelf) { + handleJsExcepiton(strongSelf->_pScope); + } + } + }; + scope->RegisterExtraCallback(hippy::kAsyncTaskEndKey, taskEndCB); + dispatch_semaphore_t scopeSemaphore = dispatch_semaphore_create(0); - __weak HippyJSExecutor *weakSelf = self; footstone::TimePoint startPoint = footstone::TimePoint::SystemNow(); engine->GetEngine()->GetJsTaskRunner()->PostTask([weakSelf, scopeSemaphore, startPoint](){ @autoreleasepool { @@ -727,4 +737,29 @@ - (NSString *)completeWSURLWithBridge:(HippyBridge *)bridge { return [devInfo assembleFullWSURLWithClientId:clientId contextName:bridge.contextName]; } + +#pragma mark - Exception Handle + +static void handleJsExcepiton(std::shared_ptr scope) { + if (!scope) { + return; + } + std::shared_ptr context = std::static_pointer_cast(scope->GetContext()); + std::shared_ptr exception = std::static_pointer_cast(context->GetException()); + if (exception) { + // if native does not handled, rethrow to js + if (!context->IsExceptionHandled()) { + hippy::vm::VM::HandleException(context, kHippyExceptionEventName, exception); + } + string_view exceptionStrView = context->GetExceptionMessage(exception); + auto errU8Str = StringViewUtils::ConvertEncoding(exceptionStrView, string_view::Encoding::Utf8).utf8_value(); + std::string errStr = StringViewUtils::ToStdString(errU8Str); + NSError *error = HippyErrorWithMessage([NSString stringWithUTF8String:errStr.c_str()]); + HippyFatal(error); + context->SetException(nullptr); + context->SetExceptionHandled(true); + } +} + + @end