diff --git a/README.md b/README.md index a3a9a3990f3..9e7e17ac22b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Hippy Group](https://img.shields.io/badge/group-Hippy-blue.svg) [![license](https://img.shields.io/badge/license-Apache%202-blue)](https://github.com/Tencent/Hippy/blob/master/LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Tencent/Hippy/pulls) ![node](https://img.shields.io/badge/node-%3E%3D10.0.0-green.svg) [![Actions Status](https://github.com/Tencent/Hippy/workflows/build/badge.svg?branch=master)](https://github.com/Tencent/Hippy/actions) [![Codecov](https://img.shields.io/codecov/c/github/Tencent/Hippy)](https://codecov.io/gh/Tencent/Hippy) [![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/Tencent/Hippy)](https://github.com/Tencent/Hippy/releases) -[Homepage](//tencent.github.io/Hippy/) +[Homepage](https://openhippy.com) ## 💡 Introduction diff --git a/dom/src/dom/dom_node.cc b/dom/src/dom/dom_node.cc index 01d5379ae5e..4e569582c28 100644 --- a/dom/src/dom/dom_node.cc +++ b/dom/src/dom/dom_node.cc @@ -322,9 +322,13 @@ LayoutResult DomNode::GetLayoutInfoFromRoot() { void DomNode::TransferLayoutOutputsRecursive(std::vector>& changed_nodes) { auto not_equal = std::not_equal_to<>(); bool changed = layout_node_->IsDirty() || layout_node_->HasNewLayout(); +#ifdef __ANDROID__ + bool trigger_layout_event = true; +#else bool trigger_layout_event = not_equal(layout_.left, layout_node_->GetLeft()) || not_equal(layout_.top, layout_node_->GetTop()) || not_equal(layout_.width, layout_node_->GetWidth()) || not_equal(layout_.height, layout_node_->GetHeight()); +#endif layout_.left = layout_node_->GetLeft(); layout_.top = layout_node_->GetTop(); diff --git a/dom/src/dom/root_node.cc b/dom/src/dom/root_node.cc index 7310b5a087c..b4e4a13a036 100644 --- a/dom/src/dom/root_node.cc +++ b/dom/src/dom/root_node.cc @@ -67,9 +67,12 @@ void RootNode::RemoveEventListener(const std::string& name, uint64_t listener_id void RootNode::ReleaseResources() {} void RootNode::CreateDomNodes(std::vector>&& nodes) { + HP_PERF_LOG("CreateDomNodes Begin"); + for (const auto& interceptor : interceptors_) { interceptor->OnDomNodeCreate(nodes); } + HP_PERF_LOG("CreateDomNodes Interceptor callback done"); std::vector> nodes_to_create; for (const auto& node_info : nodes) { auto& node = node_info->dom_node; @@ -85,6 +88,7 @@ void RootNode::CreateDomNodes(std::vector>&& nodes) { node->HandleEvent(event); OnDomNodeCreated(node); } + HP_PERF_LOG("CreateDomNodes Nodes created and finished callback"); for (const auto& node : nodes_to_create) { node->SetRenderInfo({node->GetId(), node->GetPid(), node->GetSelfIndex()}); } @@ -94,6 +98,7 @@ void RootNode::CreateDomNodes(std::vector>&& nodes) { if (!nodes_to_create.empty()) { dom_operations_.push_back({DomOperation::Op::kOpCreate, nodes_to_create}); } + HP_PERF_LOG("CreateDomNodes End"); } void RootNode::UpdateDomNodes(std::vector>&& nodes) { @@ -272,14 +277,21 @@ void RootNode::CallFunction(uint32_t id, const std::string& name, const DomArgum } void RootNode::SyncWithRenderManager(const std::shared_ptr& render_manager) { + HP_PERF_LOG("RootNode::SyncWithRenderManager"); + unsigned long cnt = dom_operations_.size(); FlushDomOperations(render_manager); + HP_PERF_LOG("RootNode::FlushDomOperations Done, dom op count:%lld", cnt); + cnt = event_operations_.size(); FlushEventOperations(render_manager); + HP_PERF_LOG("RootNode::FlushEventOperations Done, event op count:%d",cnt); DoAndFlushLayout(render_manager); + HP_PERF_LOG("RootNode::DoAndFlushLayout Done"); auto dom_manager = dom_manager_.lock(); if (dom_manager) { dom_manager->RecordDomEndTimePoint(); } render_manager->EndBatch(GetWeakSelf()); + HP_PERF_LOG("RootNode::SyncWithRenderManager End"); } void RootNode::AddEvent(uint32_t id, const std::string& event_name) { @@ -422,6 +434,7 @@ void RootNode::DoAndFlushLayout(const std::shared_ptr& render_man void RootNode::FlushDomOperations(const std::shared_ptr& render_manager) { for (auto& dom_operation : dom_operations_) { + HP_PERF_LOG("RootNode::FlushDomOperations dom_operation.op cnt:%lld", dom_operation.nodes.size()); MarkLayoutNodeDirty(dom_operation.nodes); switch (dom_operation.op) { case DomOperation::Op::kOpCreate: diff --git a/driver/js/include/driver/js_driver_utils.h b/driver/js/include/driver/js_driver_utils.h index dca8fb8e452..7a9a36cad04 100644 --- a/driver/js/include/driver/js_driver_utils.h +++ b/driver/js/include/driver/js_driver_utils.h @@ -53,8 +53,8 @@ class JsDriverUtils { const string_view& global_config, std::function)>&& scope_initialized_callback, const JsCallback& call_host_callback); - static void DestroyInstance(const std::shared_ptr& engine, - const std::shared_ptr& scope, + static void DestroyInstance(std::shared_ptr&& engine, + std::shared_ptr&& scope, const std::function& callback, bool is_reload); static bool RunScript(const std::shared_ptr& scope, diff --git a/driver/js/src/js_driver_utils.cc b/driver/js/src/js_driver_utils.cc index 0ecce2155f3..1e9bfc4af4a 100644 --- a/driver/js/src/js_driver_utils.cc +++ b/driver/js/src/js_driver_utils.cc @@ -379,28 +379,10 @@ bool JsDriverUtils::RunScript(const std::shared_ptr& scope, return flag; } -void JsDriverUtils::DestroyInstance(const std::shared_ptr& engine, - const std::shared_ptr& scope, +void JsDriverUtils::DestroyInstance(std::shared_ptr&& engine, + std::shared_ptr&& scope, const std::function& callback, bool is_reload) { - auto scope_destroy_callback = [engine, scope, is_reload, callback] { -#if defined(JS_V8) && defined(ENABLE_INSPECTOR) && !defined(V8_WITHOUT_INSPECTOR) - auto v8_vm = std::static_pointer_cast(engine->GetVM()); - if (v8_vm->IsDebug()) { - auto inspector_client = v8_vm->GetInspectorClient(); - if (inspector_client) { - auto inspector_context = scope->GetInspectorContext(); - inspector_client->DestroyInspectorContext(is_reload, inspector_context); - } - } else { - scope->WillExit(); - } -#else - scope->WillExit(); -#endif - FOOTSTONE_LOG(INFO) << "js destroy end"; - callback(true); - }; auto vm = engine->GetVM(); auto group = vm->GetGroupId(); if (vm->IsDebug()) { @@ -423,6 +405,33 @@ void JsDriverUtils::DestroyInstance(const std::shared_ptr& engine, } } auto runner = engine->GetJsTaskRunner(); + + // DestroyInstance is called in the bridge thread, while the + // scope_destroy_callback is pushed into the task_runner to run in the DOM + // thread. When DestroyInstance is called, it holds the scope and engine. + // However, executing scope_destroy_callback may add tasks (e.g., setTimeout) + // holding the scope, even when the engine is destroyed. To prevent this, move + // the scope and engine into the scope_destroy_callback, which will be released + // when the callback is executed, ensuring no other tasks can be added to the + // task runner. + auto scope_destroy_callback = [engine = std::move(engine), scope = std::move(scope), is_reload, callback] { +#if defined(JS_V8) && defined(ENABLE_INSPECTOR) && !defined(V8_WITHOUT_INSPECTOR) + auto v8_vm = std::static_pointer_cast(engine->GetVM()); + if (v8_vm->IsDebug()) { + auto inspector_client = v8_vm->GetInspectorClient(); + if (inspector_client) { + auto inspector_context = scope->GetInspectorContext(); + inspector_client->DestroyInspectorContext(is_reload, inspector_context); + } + } else { + scope->WillExit(); + } +#else + scope->WillExit(); +#endif + FOOTSTONE_LOG(INFO) << "js destroy end"; + callback(true); + }; runner->PostTask(std::move(scope_destroy_callback)); FOOTSTONE_DLOG(INFO) << "destroy, group = " << group; } diff --git a/driver/js/src/modules/scene_builder_module.cc b/driver/js/src/modules/scene_builder_module.cc index 27a8f6bfb6f..07468ce1d25 100644 --- a/driver/js/src/modules/scene_builder_module.cc +++ b/driver/js/src/modules/scene_builder_module.cc @@ -1,4 +1,4 @@ -/* + /* * * Tencent is pleased to support the open source community by making * Hippy available. @@ -27,6 +27,7 @@ #include "driver/modules/scene_builder_module.h" #include "driver/modules/ui_manager_module.h" #include "driver/scope.h" +#include "footstone/logging.h" #include "footstone/string_view.h" #include "footstone/string_view_utils.h" @@ -419,12 +420,15 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea size_t argument_count, const std::shared_ptr arguments[], std::shared_ptr&) -> std::shared_ptr { + HP_PERF_LOG("SceneBuilder.create()"); auto scope = weak_scope.lock(); if (!scope) { + HP_PERF_LOG("SceneBuilder.create() exit with error"); return nullptr; } auto ret = HandleJsValue(scope->GetContext(), arguments[0], scope); SceneBuilder::Create(scope->GetDomManager(), scope->GetRootNode(), std::move(std::get<2>(ret))); + HP_PERF_LOG("SceneBuilder.create() End"); return nullptr; }; class_template.functions.emplace_back(std::move(create_func_def)); @@ -436,12 +440,16 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea size_t argument_count, const std::shared_ptr arguments[], std::shared_ptr&) -> std::shared_ptr { + HP_PERF_LOG("SceneBuilder.update()"); auto scope = weak_scope.lock(); if (!scope) { + HP_PERF_LOG("SceneBuilder.update() exit with error"); return nullptr; } auto ret = HandleJsValue(scope->GetContext(), arguments[0], scope); SceneBuilder::Update(scope->GetDomManager(), scope->GetRootNode(), std::move(std::get<2>(ret))); + HP_PERF_LOG("SceneBuilder.update() End"); + return nullptr; }; class_template.functions.emplace_back(std::move(update_func_def)); @@ -452,8 +460,11 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea const std::shared_ptr arguments[], std::shared_ptr&) -> std::shared_ptr { + HP_PERF_LOG("SceneBuilder.move()"); + auto scope = weak_scope.lock(); if (!scope) { + HP_PERF_LOG("SceneBuilder.move() exit with error"); return nullptr; } auto weak_dom_manager = scope->GetDomManager(); @@ -469,11 +480,13 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea auto node = context->CopyArrayElement(info, 0); auto id_tuple = GetNodeId(context, node); if (!std::get<0>(id_tuple)) { + HP_PERF_LOG("SceneBuilder.move() exit with error"); return nullptr; } auto pid_tuple = GetNodePid(context, node); if (!std::get<0>(pid_tuple)) { + HP_PERF_LOG("SceneBuilder.move() exit with error"); return nullptr; } if (length >= 2) { @@ -489,6 +502,7 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea } } SceneBuilder::Move(weak_dom_manager, scope->GetRootNode(), std::move(dom_infos)); + HP_PERF_LOG("SceneBuilder.move() End"); return nullptr; }; class_template.functions.emplace_back(std::move(move_func_def)); @@ -500,8 +514,11 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea size_t argument_count, const std::shared_ptr arguments[], std::shared_ptr&) -> std::shared_ptr { + HP_PERF_LOG("SceneBuilder.delete()"); + auto scope = weak_scope.lock(); if (!scope) { + HP_PERF_LOG("SceneBuilder.delete() exit with error"); return nullptr; } auto nodes = arguments[0]; @@ -521,6 +538,8 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea auto pid_tuple = GetNodePid(context, node); if (!std::get<0>(pid_tuple)) { + HP_PERF_LOG("SceneBuilder.delete() exit with error"); + return nullptr; } dom_infos.push_back(std::make_shared( @@ -532,6 +551,8 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea } } SceneBuilder::Delete(scope->GetDomManager(), scope->GetRootNode(), std::move(dom_infos)); + HP_PERF_LOG("SceneBuilder.delete() End"); + return nullptr; }; class_template.functions.emplace_back(std::move(delete_func_def)); @@ -543,14 +564,17 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea size_t argument_count, const std::shared_ptr arguments[], std::shared_ptr&) -> std::shared_ptr { + HP_PERF_LOG("SceneBuilder.addEventListener()"); auto scope = weak_scope.lock(); if (!scope) { + HP_PERF_LOG("SceneBuilder.addEventListener() exit with error"); return nullptr; } Scope::EventListenerInfo listener_info; HandleEventListenerInfo(scope->GetContext(), argument_count, arguments, listener_info); auto dom_listener_info = scope->AddListener(listener_info); SceneBuilder::AddEventListener(scope->GetDomManager(), scope->GetRootNode(), dom_listener_info); + HP_PERF_LOG("SceneBuilder.addEventListener() End"); return nullptr; }; class_template.functions.emplace_back(std::move(add_event_listener_def)); @@ -562,14 +586,18 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea size_t argument_count, const std::shared_ptr arguments[], std::shared_ptr&) -> std::shared_ptr { + HP_PERF_LOG("SceneBuilder.removeEventListener()"); + auto scope = weak_scope.lock(); if (!scope) { + HP_PERF_LOG("SceneBuilder.removeEventListener() exit with error"); return nullptr; } Scope::EventListenerInfo listener_info; HandleEventListenerInfo(scope->GetContext(), argument_count, arguments, listener_info); auto dom_listener_info = scope->RemoveListener(listener_info); SceneBuilder::RemoveEventListener(scope->GetDomManager(), scope->GetRootNode(), dom_listener_info); + HP_PERF_LOG("SceneBuilder.removeEventListener() End"); return nullptr; }; class_template.functions.emplace_back(std::move(remove_event_listener_def)); @@ -582,11 +610,14 @@ std::shared_ptr> RegisterSceneBuilder(const std::wea size_t argument_count, const std::shared_ptr arguments[], std::shared_ptr&) -> std::shared_ptr { + HP_PERF_LOG("SceneBuilder.build()"); auto scope = weak_scope.lock(); if (!scope) { + HP_PERF_LOG("SceneBuilder.build() exit with error"); return nullptr; } SceneBuilder::Build(scope->GetDomManager(), scope->GetRootNode()); + HP_PERF_LOG("SceneBuilder.build() End"); return nullptr; }; class_template.functions.emplace_back(std::move(build_func_def)); diff --git a/driver/js/src/napi/jsc/jsc_ctx.cc b/driver/js/src/napi/jsc/jsc_ctx.cc index de1dff41291..4d58c8a0482 100644 --- a/driver/js/src/napi/jsc/jsc_ctx.cc +++ b/driver/js/src/napi/jsc/jsc_ctx.cc @@ -30,6 +30,7 @@ #include "driver/vm/native_source_code.h" #include "driver/vm/jsc/jsc_vm.h" + namespace hippy { inline namespace driver { inline namespace napi { @@ -665,8 +666,8 @@ bool JSCCtx::IsObject(const std::shared_ptr& value) { } string_view JSCCtx::CopyFunctionName(const std::shared_ptr& function) { - FOOTSTONE_UNIMPLEMENTED(); - return ""; + FOOTSTONE_UNIMPLEMENTED(); + return ""; } bool JSCCtx::GetEntriesFromObject(const std::shared_ptr& value, @@ -892,9 +893,12 @@ std::shared_ptr JSCCtx::CallFunction(const std::shared_ptr& const std::shared_ptr argv[]) { auto function_value = std::static_pointer_cast(function); JSValueRef exception = nullptr; + HP_PERF_LOG("JSCCtx::CallFunction"); auto function_object = JSValueToObject(context_, function_value->value_, &exception); if (exception) { SetException(std::make_shared(context_, exception)); + HP_PERF_LOG("JSCCtx::CallFunction End with exception"); + return nullptr; } @@ -902,6 +906,7 @@ 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)); + HP_PERF_LOG("JSCCtx::CallFunction End with exception"); return nullptr; } @@ -909,8 +914,10 @@ 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)); + HP_PERF_LOG("JSCCtx::CallFunction End with exception"); return nullptr; } + HP_PERF_LOG("JSCCtx::CallFunction End with exception"); return std::make_shared(context_, ret_value_ref); } @@ -923,12 +930,15 @@ 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)); + HP_PERF_LOG("JSCCtx::CallFunction End with exception"); return nullptr; } if (!ret_value_ref) { + HP_PERF_LOG("JSCCtx::CallFunction End with exception"); return nullptr; } + HP_PERF_LOG("JSCCtx::CallFunction End with exception"); return std::make_shared(context_, ret_value_ref); } @@ -1124,6 +1134,7 @@ std::shared_ptr JSCCtx::RunScript(const string_view& data, if (StringViewUtils::IsEmpty(data)) { return nullptr; } + HP_PERF_LOG("JSCCtx::RunScript"); JSStringRef js = JSCVM::CreateJSCString(data); JSValueRef exception = nullptr; @@ -1139,13 +1150,15 @@ std::shared_ptr JSCCtx::RunScript(const string_view& data, if (exception) { SetException(std::make_shared(context_, exception)); + HP_PERF_LOG("JSCCtx::RunScript Error"); return nullptr; } if (!value) { + HP_PERF_LOG("JSCCtx::RunScript Error"); return nullptr; } - + HP_PERF_LOG("JSCCtx::RunScript End"); return std::make_shared(context_, value); } diff --git a/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc b/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc index b2eff77f78b..9f56462191a 100644 --- a/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc +++ b/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc @@ -51,6 +51,8 @@ #include "vfs/uri.h" #include "vfs/vfs_resource_holder.h" +#include + #ifdef JS_V8 #include "driver/vm/v8/v8_vm.h" #endif @@ -368,14 +370,13 @@ void DestroyJsDriver(__unused JNIEnv* j_env, auto scope_id = footstone::checked_numeric_cast(j_scope_id); auto flag = hippy::global_data_holder.Erase(scope_id); FOOTSTONE_CHECK(flag); - JsDriverUtils::DestroyInstance(engine, scope, [bridge_callback_object](bool ret) { + JsDriverUtils::DestroyInstance(std::move(engine), std::move(scope), [bridge_callback_object](bool ret) { if (ret) { hippy::bridge::CallJavaMethod(bridge_callback_object->GetObj(),INIT_CB_STATE::SUCCESS); } else { hippy::bridge::CallJavaMethod(bridge_callback_object->GetObj(),INIT_CB_STATE::DESTROY_ERROR); } }, static_cast(j_is_reload)); - scope = nullptr; } void LoadInstance(JNIEnv* j_env, diff --git a/framework/android/src/main/java/com/tencent/mtt/hippy/adapter/font/DefaultFontScaleAdapter.java b/framework/android/src/main/java/com/tencent/mtt/hippy/adapter/font/DefaultFontScaleAdapter.java index fcbcff1d81f..91f3c90f4d9 100644 --- a/framework/android/src/main/java/com/tencent/mtt/hippy/adapter/font/DefaultFontScaleAdapter.java +++ b/framework/android/src/main/java/com/tencent/mtt/hippy/adapter/font/DefaultFontScaleAdapter.java @@ -13,27 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.tencent.mtt.hippy.adapter.font; -import com.tencent.mtt.hippy.utils.LogUtils; +import android.graphics.Typeface; @SuppressWarnings({"unused"}) public class DefaultFontScaleAdapter implements HippyFontScaleAdapter { - @Override - public float getFontScale() { - return 1; - } + @Override + public float getFontScale() { + return 1; + } + + @Override + public CharSequence getEmoticonText(CharSequence text, int fontSize) { + return text; + } - @Override - public CharSequence getEmoticonText(CharSequence text, int fontSize) { - return text; - } + @Override + public String getCustomFontFilePath(String fontFamilyName, int style) { + return null; + } - @Override - public String getCustomFontFilePath(String fontFamilyName, int style) { - LogUtils.d("DefaultFontScaleAdapter", - "getCustomFontFilePath fontFamilyName=" + fontFamilyName + ", style=" + style); - return null; - } + @Override + public Typeface getCustomTypeface(String fontFamily, int style) { + return null; + } } diff --git a/modules/footstone/include/footstone/logging.h b/modules/footstone/include/footstone/logging.h index 9df4862185e..e31c8f9ce08 100644 --- a/modules/footstone/include/footstone/logging.h +++ b/modules/footstone/include/footstone/logging.h @@ -20,6 +20,8 @@ #pragma once +#if defined(__cplusplus) + #include #include #include @@ -105,7 +107,29 @@ class LogMessage { } delegate_ = delegate; } - + inline static void LogWithFormat(const char * file, int line, const char *format, ...){ + char *log_msg = NULL; + va_list args; + va_start(args, format); + int ret = vasprintf(&log_msg, format, args); + va_end(args); + + if (ret <= 0 && log_msg == NULL) { + return; + } + + std::ostringstream s; + s<<"thread:"<= GetMinLogLevel(); } diff --git a/modules/ios/base/HippyLog.h b/modules/ios/base/HippyLog.h index 24b17c5032e..066421f5a86 100644 --- a/modules/ios/base/HippyLog.h +++ b/modules/ios/base/HippyLog.h @@ -19,6 +19,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +# if defined(__OBJC__) #import #import "HippyDefines.h" @@ -134,3 +135,4 @@ HIPPY_EXTERN void HippyPerformBlockWithLogPrefix(void (^block)(void), NSString * HIPPY_EXTERN void HippyLogNativeInternal(HippyLogLevel, const char *, int, NSString *, ...) NS_FORMAT_FUNCTION(4, 5); +#endif // defined(__OBJC__) diff --git a/renderer/native/android/src/main/cpp/src/renderer/native_render_jni.cc b/renderer/native/android/src/main/cpp/src/renderer/native_render_jni.cc index aae9ee40716..d82e958ecac 100644 --- a/renderer/native/android/src/main/cpp/src/renderer/native_render_jni.cc +++ b/renderer/native/android/src/main/cpp/src/renderer/native_render_jni.cc @@ -251,41 +251,47 @@ void DoCallBack(JNIEnv *j_env, jobject j_object, return; } - auto& root_map = RootNode::PersistentMap(); - std::shared_ptr root_node; uint32_t root_id = footstone::check::checked_numeric_cast(j_root_id); - ret = root_map.Find(root_id, root_node); - if (!ret) { - FOOTSTONE_DLOG(WARNING) << "DoCallBack root_node is nullptr"; - return; - } - - auto node = dom_manager->GetNode(root_node, - footstone::check::checked_numeric_cast(j_node_id)); - if (node == nullptr) { - FOOTSTONE_DLOG(WARNING) << "DoCallBack DomNode not found for id: " << j_node_id; - return; - } - + uint32_t node_id = footstone::check::checked_numeric_cast(j_node_id); + uint32_t cb_id = footstone::check::checked_numeric_cast(j_cb_id); jboolean is_copy = JNI_TRUE; - const char* func_name = j_env->GetStringUTFChars(j_func_name, &is_copy); - auto callback = node->GetCallback(func_name, - footstone::check::checked_numeric_cast(j_cb_id)); - if (callback == nullptr) { - FOOTSTONE_DLOG(WARNING) << "DoCallBack Callback not found for func_name: " << func_name; - return; - } + const char* c = j_env->GetStringUTFChars(j_func_name, &is_copy); + std::string func_name(c); std::shared_ptr params = std::make_shared(); if (j_buffer != nullptr && j_length > 0) { jbyte params_buffer[j_length]; j_env->GetByteArrayRegion(j_buffer, j_offset, j_length, params_buffer); footstone::value::Deserializer deserializer((const uint8_t*) params_buffer, - footstone::check::checked_numeric_cast(j_length)); + footstone::check::checked_numeric_cast(j_length)); deserializer.ReadHeader(); deserializer.ReadValue(*params); } - callback(std::make_shared(*params)); + + std::vector> ops = {[root_id, node_id, cb_id, func_name, dom_manager, params]{ + auto& root_map = RootNode::PersistentMap(); + std::shared_ptr root_node; + bool ret = root_map.Find(root_id, root_node); + if (!ret) { + FOOTSTONE_DLOG(WARNING) << "DoCallBack root_node is nullptr"; + return; + } + + auto node = dom_manager->GetNode(root_node, node_id); + if (node == nullptr) { + FOOTSTONE_DLOG(WARNING) << "DoCallBack DomNode not found for id: " << node_id; + return; + } + + auto callback = node->GetCallback(func_name, cb_id); + if (callback == nullptr) { + FOOTSTONE_DLOG(WARNING) << "DoCallBack Callback not found for func_name: " << func_name; + return; + } + + callback(std::make_shared(*params)); + }}; + dom_manager->PostTask(Scene(std::move(ops))); } void OnReceivedEvent(JNIEnv* j_env, jobject j_object, jint j_render_manager_id, jint j_root_id, jint j_dom_id, jstring j_event_name, diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java b/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java index 402a1497b29..d8dc78ec43a 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/NativeRenderer.java @@ -405,7 +405,6 @@ public void onResume() { listener.onInstanceResume(); } } - ChoreographerUtils.onResume(); } @Override @@ -415,7 +414,6 @@ public void onPause() { listener.onInstancePause(); } } - ChoreographerUtils.onPause(); } @MainThread diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontAdapter.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontAdapter.java index 45c0c2bf1d4..bdf09d96d98 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontAdapter.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontAdapter.java @@ -16,6 +16,8 @@ package com.tencent.renderer.component.text; +import android.graphics.Typeface; + /** * Provide and implement by host */ @@ -45,4 +47,13 @@ public interface FontAdapter { * @return a {@link String} that represents custom font file path */ String getCustomFontFilePath(String fontFamily, int style); + + /** + * Get the type face customized by the host. + * + * @param fontFamily the property of text node + * @param style the typeface's intrinsic style attributes + * @return a {@link Typeface} + */ + Typeface getCustomTypeface(String fontFamily, int style); } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java index 91ffa6d562b..1971746d376 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/TypeFaceUtil.java @@ -38,13 +38,17 @@ public class TypeFaceUtil { public static Typeface getTypeface(String fontFamilyName, int style, @Nullable FontAdapter fontAdapter) { - String cache = fontFamilyName + style; - Typeface typeface = sFontCache.get(cache); + Typeface typeface = + (fontAdapter != null) ? fontAdapter.getCustomTypeface(fontFamilyName, style) : null; if (typeface == null) { - typeface = createTypeface(fontFamilyName, style, fontAdapter); - } - if (typeface != null) { - sFontCache.put(cache, typeface); + String cache = fontFamilyName + style; + typeface = sFontCache.get(cache); + if (typeface == null) { + typeface = createTypeface(fontFamilyName, style, fontAdapter); + } + if (typeface != null) { + sFontCache.put(cache, typeface); + } } return typeface; } @@ -56,7 +60,8 @@ private static Typeface createTypeface(String fontFamilyName, int style, for (String fileExtension : FONT_EXTENSIONS) { String fileName = FONTS_PATH + fontFamilyName + extension + fileExtension; try { - typeface = Typeface.createFromAsset(ContextHolder.getAppContext().getAssets(), fileName); + typeface = Typeface.createFromAsset(ContextHolder.getAppContext().getAssets(), + fileName); if (typeface != null) { return typeface; } @@ -71,7 +76,8 @@ private static Typeface createTypeface(String fontFamilyName, int style, fileName = FONTS_PATH + fontFamilyName + fileExtension; try { typeface = Typeface.create( - Typeface.createFromAsset(ContextHolder.getAppContext().getAssets(), fileName), style); + Typeface.createFromAsset(ContextHolder.getAppContext().getAssets(), + fileName), style); if (typeface != null) { return typeface; } diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/utils/ChoreographerUtils.java b/renderer/native/android/src/main/java/com/tencent/renderer/utils/ChoreographerUtils.java index c74922a0377..ce113fe8088 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/utils/ChoreographerUtils.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/utils/ChoreographerUtils.java @@ -26,7 +26,6 @@ public class ChoreographerUtils { public static final String DO_FRAME = "frameUpdate"; private static boolean sEnablePostFrame = false; - private static boolean sInForeground = true; private static HashMap> sListeners = null; private static void handleDoFrameCallback() { @@ -44,7 +43,7 @@ private static void handleDoFrameCallback() { private static void doPostFrame() { Choreographer.FrameCallback frameCallback = frameTimeNanos -> { - if (sEnablePostFrame && sInForeground) { + if (sEnablePostFrame) { handleDoFrameCallback(); doPostFrame(); } @@ -52,19 +51,6 @@ private static void doPostFrame() { Choreographer.getInstance().postFrameCallback(frameCallback); } - @MainThread - public static void onResume() { - sInForeground = true; - if (sEnablePostFrame) { - doPostFrame(); - } - } - - @MainThread - public static void onPause() { - sInForeground = false; - } - /** * Register frame callback listener, should call in ui thread. * diff --git a/renderer/native/ios/renderer/HippyUIManager.mm b/renderer/native/ios/renderer/HippyUIManager.mm index 548405e3ab3..9dae617ccfb 100644 --- a/renderer/native/ios/renderer/HippyUIManager.mm +++ b/renderer/native/ios/renderer/HippyUIManager.mm @@ -678,6 +678,9 @@ - (void)flushUIBlocksOnRootNode:(std::weak_ptr)rootNode { if (!strongRootNode) { return; } + unsigned int rand = arc4random(); + HP_PERF_LOG("flushUIBlocksOnRootNode(random id:%u", rand); + int32_t rootTag = strongRootNode->GetId(); NSArray *previousPendingUIBlocks = _pendingUIBlocks; _pendingUIBlocks = [NSMutableArray new]; @@ -686,18 +689,24 @@ - (void)flushUIBlocksOnRootNode:(std::weak_ptr)rootNode { // Execute the previously queued UI blocks dispatch_async(dispatch_get_main_queue(), ^{ if (weakManager) { + HP_PERF_LOG("flushUIBlocksOnRootNode on main thread(random id:%u)",rand); + int cnt = 0; + HippyUIManager *strongSelf = weakManager; NSDictionary *viewReg = [strongSelf->_viewRegistry componentsForRootTag:@(rootTag)]; @try { for (HippyViewManagerUIBlock block in previousPendingUIBlocks) { block(strongSelf, viewReg); + ++cnt; } } @catch (NSException *exception) { } + HP_PERF_LOG("flushUIBlocksOnRootNode on main thread done, block count:%d(random id:%u)", cnt, rand); } }); } + HP_PERF_LOG("flushUIBlocksOnRootNode End(random id:%u)",rand); } #pragma mark - diff --git a/renderer/native/ios/renderer/NativeRenderManager.mm b/renderer/native/ios/renderer/NativeRenderManager.mm index b24ca5c313a..45cf4231e05 100644 --- a/renderer/native/ios/renderer/NativeRenderManager.mm +++ b/renderer/native/ios/renderer/NativeRenderManager.mm @@ -111,14 +111,21 @@ void NativeRenderManager::EndBatch(std::weak_ptr root_node) { @autoreleasepool { + HP_PERF_LOG("NativeRenderManager::EndBatch"); HippyAssert(renderImpl_, @"renderImpl_ is null, did you forget to call Initialize()?"); [renderImpl_ batchOnRootNode:root_node]; + HP_PERF_LOG("NativeRenderManager::EndBatch End"); + } } -void NativeRenderManager::BeforeLayout(std::weak_ptr root_node) {} +void NativeRenderManager::BeforeLayout(std::weak_ptr root_node) { + HP_PERF_LOG("NativeRenderManager::BeforeLayout"); +} -void NativeRenderManager::AfterLayout(std::weak_ptr root_node) {} +void NativeRenderManager::AfterLayout(std::weak_ptr root_node) { + HP_PERF_LOG("NativeRenderManager::AfterLayout"); +} void NativeRenderManager::AddEventListener(std::weak_ptr root_node, std::weak_ptr dom_node, diff --git a/renderer/native/ios/renderer/component/text/NativeRenderObjectText.mm b/renderer/native/ios/renderer/component/text/NativeRenderObjectText.mm index 5d9701ff8df..f62e5760264 100644 --- a/renderer/native/ios/renderer/component/text/NativeRenderObjectText.mm +++ b/renderer/native/ios/renderer/component/text/NativeRenderObjectText.mm @@ -238,7 +238,7 @@ - (void)amendLayoutBeforeMount:(NSMutableSet *)blocks [textStorage enumerateAttribute:NativeRenderRenderObjectAttributeName inRange:characterRange options:0 usingBlock:^( HippyShadowView *child, NSRange range, __unused BOOL *_) { if (child) { - float width = child.frame.size.width, height = child.frame.size.height; + float width = child.width, height = child.height; if (isnan(width) || isnan(height)) { HippyLogError(@"Views nested within a must have a width and height"); } @@ -254,8 +254,8 @@ - (void)amendLayoutBeforeMount:(NSMutableSet *)blocks // take margin into account // FIXME: margin currently not working, may have some bug in layout process - float left = child.nodeLayoutResult.left; - float top = child.nodeLayoutResult.top; + float left = 0; + float top = 0; float marginV = child.nodeLayoutResult.marginTop + child.nodeLayoutResult.marginBottom; CGFloat roundedHeightWithMargin = NativeRenderRoundPixelValue(height + marginV); diff --git a/renderer/native/ios/renderer/component/view/HippyShadowView.h b/renderer/native/ios/renderer/component/view/HippyShadowView.h index 6a60e9a4b96..33c0372da0d 100644 --- a/renderer/native/ios/renderer/component/view/HippyShadowView.h +++ b/renderer/native/ios/renderer/component/view/HippyShadowView.h @@ -118,6 +118,23 @@ extern NSString *const NativeRenderShadowViewDiffTag; */ @property (nonatomic, assign, getter=isHidden) BOOL hidden; +/** + * Position and dimensions. + * Defaults to 0 + */ +@property (nonatomic, assign) CGFloat top; +@property (nonatomic, assign) CGFloat left; +@property (nonatomic, assign) CGFloat bottom; +@property (nonatomic, assign) CGFloat right; + +@property (nonatomic, assign) CGFloat width; +@property (nonatomic, assign) CGFloat height; + +@property (nonatomic, assign) CGFloat minWidth; +@property (nonatomic, assign) CGFloat maxWidth; +@property (nonatomic, assign) CGFloat minHeight; +@property (nonatomic, assign) CGFloat maxHeight; + /** * Get frame set by layout system */