From aea24e3c81b708f8d6b21573e24dd50efe0c9a52 Mon Sep 17 00:00:00 2001 From: etkmao Date: Tue, 10 Sep 2024 15:54:04 +0800 Subject: [PATCH] refactor(ios): avoid mutex crash in special app environment (#4020) * fix(ios): check static invalid mutex crash * fix(ios): move static maps to heap for checking static overflow crash --- dom/include/dom/layout_node.h | 1 + dom/src/dom/root_node.cc | 1 + dom/src/dom/taitank_layout_node.cc | 145 +++++++++++--------- dom/src/dom/yoga_layout_node.cc | 1 + driver/js/include/driver/napi/jsc/jsc_ctx.h | 22 +++ driver/js/include/driver/vm/jsc/jsc_vm.h | 7 - driver/js/src/napi/jsc/jsc_ctx.cc | 12 +- driver/js/src/vm/jsc/jsc_vm.cc | 18 --- 8 files changed, 113 insertions(+), 94 deletions(-) diff --git a/dom/include/dom/layout_node.h b/dom/include/dom/layout_node.h index 8346c54540c..01a0ec3f684 100644 --- a/dom/include/dom/layout_node.h +++ b/dom/include/dom/layout_node.h @@ -124,6 +124,7 @@ class LayoutNode { const std::vector& style_delete) = 0; }; +void InitLayoutConsts(); std::shared_ptr CreateLayoutNode(); } // namespace dom diff --git a/dom/src/dom/root_node.cc b/dom/src/dom/root_node.cc index 6e737cd9f01..eb94863ea70 100644 --- a/dom/src/dom/root_node.cc +++ b/dom/src/dom/root_node.cc @@ -101,6 +101,7 @@ bool DomNodeStyleDiffer::Calculate(const std::shared_ptr& } RootNode::RootNode(uint32_t id) : DomNode(id, 0, 0, "", "", nullptr, nullptr, {}) { + InitLayoutConsts(); SetRenderInfo({id, 0, 0}); animation_manager_ = std::make_shared(); interceptors_.push_back(animation_manager_); diff --git a/dom/src/dom/taitank_layout_node.cc b/dom/src/dom/taitank_layout_node.cc index a21024d6c73..ff9fdb7f500 100644 --- a/dom/src/dom/taitank_layout_node.cc +++ b/dom/src/dom/taitank_layout_node.cc @@ -30,75 +30,82 @@ namespace hippy { inline namespace dom { -const std::map kOverflowMap = {{"visible", OverflowType::OVERFLOW_VISIBLE}, - {"hidden", OverflowType::OVERFLOW_HIDDEN}, - {"scroll", OverflowType::OVERFLOW_SCROLL}}; - -const std::map kFlexDirectionMap = { - {"row", FlexDirection::FLEX_DIRECTION_ROW}, - {"row-reverse", FlexDirection::FLEX_DIRECTION_ROW_REVERSE}, - {"column", FlexDirection::FLEX_DIRECTION_COLUMN}, - {"column-reverse", FlexDirection::FLEX_DIRECTION_COLUNM_REVERSE}}; - -const std::map kWrapModeMap = {{"nowrap", FlexWrapMode::FLEX_NO_WRAP}, - {"wrap", FlexWrapMode::FLEX_WRAP}, - {"wrap-reverse", FlexWrapMode::FLEX_WRAP_REVERSE}}; - -const std::map kJustifyMap = {{"flex-start", FlexAlign::FLEX_ALIGN_START}, - {"center", FlexAlign::FLEX_ALIGN_CENTER}, - {"flex-end", FlexAlign::FLEX_ALIGN_END}, - {"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN}, - {"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND}, - {"space-evenly", FlexAlign::FLEX_ALIGN_SPACE_EVENLY}}; - -const std::map kAlignMap = {{"auto", FlexAlign::FLEX_ALIGN_AUTO}, - {"flex-start", FlexAlign::FLEX_ALIGN_START}, - {"center", FlexAlign::FLEX_ALIGN_CENTER}, - {"flex-end", FlexAlign::FLEX_ALIGN_END}, - {"stretch", FlexAlign::FLEX_ALIGN_STRETCH}, - {"baseline", FlexAlign::FLEX_ALIGN_BASE_LINE}, - {"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN}, - {"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND}}; - -const std::map kMarginMap = {{kMargin, CSSDirection::CSS_ALL}, - {kMarginVertical, CSSDirection::CSS_VERTICAL}, - {kMarginHorizontal, CSSDirection::CSS_HORIZONTAL}, - {kMarginLeft, CSSDirection::CSS_LEFT}, - {kMarginRight, CSSDirection::CSS_RIGHT}, - {kMarginTop, CSSDirection::CSS_TOP}, - {kMarginBottom, CSSDirection::CSS_BOTTOM}}; - -const std::map kPaddingMap = {{kPadding, CSSDirection::CSS_ALL}, - {kPaddingVertical, CSSDirection::CSS_VERTICAL}, - {kPaddingHorizontal, CSSDirection::CSS_HORIZONTAL}, - {kPaddingLeft, CSSDirection::CSS_LEFT}, - {kPaddingRight, CSSDirection::CSS_RIGHT}, - {kPaddingTop, CSSDirection::CSS_TOP}, - {kPaddingBottom, CSSDirection::CSS_BOTTOM}}; - -const std::map kPositionMap = {{kLeft, CSSDirection::CSS_LEFT}, - {kRight, CSSDirection::CSS_RIGHT}, - {kTop, CSSDirection::CSS_TOP}, - {kBottom, CSSDirection::CSS_BOTTOM}}; - -const std::map kBorderMap = {{kBorderWidth, CSSDirection::CSS_ALL}, - {kBorderLeftWidth, CSSDirection::CSS_LEFT}, - {kBorderTopWidth, CSSDirection::CSS_TOP}, - {kBorderRightWidth, CSSDirection::CSS_RIGHT}, - {kBorderBottomWidth, CSSDirection::CSS_BOTTOM}}; - -const std::map kPositionTypeMap = {{"relative", PositionType::POSITION_TYPE_RELATIVE}, - {"absolute", PositionType::POSITION_TYPE_ABSOLUTE}}; - -const std::map kDisplayTypeMap = {{"none", DisplayType::DISPLAY_TYPE_NONE}}; - -const std::map kDirectionMap = { - {"inherit", DIRECTION_INHERIT}, {"ltr", DIRECTION_LTR}, {"rtl", DIRECTION_RTL}}; +class TaitankLayoutConsts { +public: + const std::map kOverflowMap = {{"visible", OverflowType::OVERFLOW_VISIBLE}, + {"hidden", OverflowType::OVERFLOW_HIDDEN}, + {"scroll", OverflowType::OVERFLOW_SCROLL}}; + + const std::map kFlexDirectionMap = { + {"row", FlexDirection::FLEX_DIRECTION_ROW}, + {"row-reverse", FlexDirection::FLEX_DIRECTION_ROW_REVERSE}, + {"column", FlexDirection::FLEX_DIRECTION_COLUMN}, + {"column-reverse", FlexDirection::FLEX_DIRECTION_COLUNM_REVERSE}}; + + const std::map kWrapModeMap = {{"nowrap", FlexWrapMode::FLEX_NO_WRAP}, + {"wrap", FlexWrapMode::FLEX_WRAP}, + {"wrap-reverse", FlexWrapMode::FLEX_WRAP_REVERSE}}; + + const std::map kJustifyMap = {{"flex-start", FlexAlign::FLEX_ALIGN_START}, + {"center", FlexAlign::FLEX_ALIGN_CENTER}, + {"flex-end", FlexAlign::FLEX_ALIGN_END}, + {"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN}, + {"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND}, + {"space-evenly", FlexAlign::FLEX_ALIGN_SPACE_EVENLY}}; + + const std::map kAlignMap = {{"auto", FlexAlign::FLEX_ALIGN_AUTO}, + {"flex-start", FlexAlign::FLEX_ALIGN_START}, + {"center", FlexAlign::FLEX_ALIGN_CENTER}, + {"flex-end", FlexAlign::FLEX_ALIGN_END}, + {"stretch", FlexAlign::FLEX_ALIGN_STRETCH}, + {"baseline", FlexAlign::FLEX_ALIGN_BASE_LINE}, + {"space-between", FlexAlign::FLEX_ALIGN_SPACE_BETWEEN}, + {"space-around", FlexAlign::FLEX_ALIGN_SPACE_AROUND}}; + + const std::map kMarginMap = {{kMargin, CSSDirection::CSS_ALL}, + {kMarginVertical, CSSDirection::CSS_VERTICAL}, + {kMarginHorizontal, CSSDirection::CSS_HORIZONTAL}, + {kMarginLeft, CSSDirection::CSS_LEFT}, + {kMarginRight, CSSDirection::CSS_RIGHT}, + {kMarginTop, CSSDirection::CSS_TOP}, + {kMarginBottom, CSSDirection::CSS_BOTTOM}}; + + const std::map kPaddingMap = {{kPadding, CSSDirection::CSS_ALL}, + {kPaddingVertical, CSSDirection::CSS_VERTICAL}, + {kPaddingHorizontal, CSSDirection::CSS_HORIZONTAL}, + {kPaddingLeft, CSSDirection::CSS_LEFT}, + {kPaddingRight, CSSDirection::CSS_RIGHT}, + {kPaddingTop, CSSDirection::CSS_TOP}, + {kPaddingBottom, CSSDirection::CSS_BOTTOM}}; + + const std::map kPositionMap = {{kLeft, CSSDirection::CSS_LEFT}, + {kRight, CSSDirection::CSS_RIGHT}, + {kTop, CSSDirection::CSS_TOP}, + {kBottom, CSSDirection::CSS_BOTTOM}}; + + const std::map kBorderMap = {{kBorderWidth, CSSDirection::CSS_ALL}, + {kBorderLeftWidth, CSSDirection::CSS_LEFT}, + {kBorderTopWidth, CSSDirection::CSS_TOP}, + {kBorderRightWidth, CSSDirection::CSS_RIGHT}, + {kBorderBottomWidth, CSSDirection::CSS_BOTTOM}}; + + const std::map kPositionTypeMap = {{"relative", PositionType::POSITION_TYPE_RELATIVE}, + {"absolute", PositionType::POSITION_TYPE_ABSOLUTE}}; + + const std::map kDisplayTypeMap = {{"none", DisplayType::DISPLAY_TYPE_NONE}}; + + const std::map kDirectionMap = { + {"inherit", DIRECTION_INHERIT}, {"ltr", DIRECTION_LTR}, {"rtl", DIRECTION_RTL}}; +}; + +static std::shared_ptr global_layout_consts = nullptr; #define TAITANK_GET_STYLE_DECL(NAME, TYPE, DEFAULT) \ static TYPE GetStyle##NAME(const std::string& key) { \ - auto iter = k##NAME##Map.find(key); \ - if (iter != k##NAME##Map.end()) return iter->second; \ + if (global_layout_consts == nullptr) return DEFAULT; \ + auto &map = global_layout_consts->k##NAME##Map; \ + auto iter = map.find(key); \ + if (iter != map.end()) return iter->second; \ return DEFAULT; \ } @@ -811,6 +818,12 @@ void TaitankLayoutNode::Deallocate() { delete engine_node_; } +void InitLayoutConsts() { + if (global_layout_consts == nullptr) { + global_layout_consts = std::make_shared(); + } +} + std::shared_ptr CreateLayoutNode() { return std::make_shared(); } } // namespace dom diff --git a/dom/src/dom/yoga_layout_node.cc b/dom/src/dom/yoga_layout_node.cc index 303d721c702..7b681694fa5 100644 --- a/dom/src/dom/yoga_layout_node.cc +++ b/dom/src/dom/yoga_layout_node.cc @@ -762,6 +762,7 @@ void YogaLayoutNode::Deallocate() { YGConfigFree(yoga_config_); } +void InitLayoutConsts() {} std::shared_ptr CreateLayoutNode() { return std::make_shared(); } } // namespace dom diff --git a/driver/js/include/driver/napi/jsc/jsc_ctx.h b/driver/js/include/driver/napi/jsc/jsc_ctx.h index d33210c3066..075837285d5 100644 --- a/driver/js/include/driver/napi/jsc/jsc_ctx.h +++ b/driver/js/include/driver/napi/jsc/jsc_ctx.h @@ -28,6 +28,7 @@ #include #include +#include #include "footstone/logging.h" #include "footstone/string_view.h" @@ -63,6 +64,27 @@ struct ConstructorData { } }; +class ConstructorDataManager { +public: + void SaveConstructorDataPtr(void* ptr) { + std::lock_guard lock(mutex_); + constructor_data_ptr_set_.insert(ptr); + } + + void ClearConstructorDataPtr(void* ptr) { + std::lock_guard lock(mutex_); + constructor_data_ptr_set_.erase(ptr); + } + + bool IsValidConstructorDataPtr(void* ptr) { + std::lock_guard lock(mutex_); + return constructor_data_ptr_set_.find(ptr) != constructor_data_ptr_set_.end(); + } +private: + std::set constructor_data_ptr_set_; + std::mutex mutex_; +}; + class JSCCtx : public Ctx { public: using string_view = footstone::string_view; diff --git a/driver/js/include/driver/vm/jsc/jsc_vm.h b/driver/js/include/driver/vm/jsc/jsc_vm.h index 2d2f25896dd..3bd0b02ae7c 100644 --- a/driver/js/include/driver/vm/jsc/jsc_vm.h +++ b/driver/js/include/driver/vm/jsc/jsc_vm.h @@ -47,13 +47,6 @@ class JSCVM : public VM, public std::enable_shared_from_this { } JSContextGroupRef vm_; - - static void SaveConstructorDataPtr(void* ptr); - static void ClearConstructorDataPtr(void* ptr); - static bool IsValidConstructorDataPtr(void* ptr); - - static std::set constructor_data_ptr_set_; - static std::mutex mutex_; virtual std::shared_ptr ParseJson(const std::shared_ptr& ctx, const string_view& json) override; virtual std::shared_ptr CreateContext() override; diff --git a/driver/js/src/napi/jsc/jsc_ctx.cc b/driver/js/src/napi/jsc/jsc_ctx.cc index 42dd83a8ce7..0610c96d2f5 100644 --- a/driver/js/src/napi/jsc/jsc_ctx.cc +++ b/driver/js/src/napi/jsc/jsc_ctx.cc @@ -49,11 +49,13 @@ constexpr char16_t kSetStr[] = u"set"; static std::once_flag global_class_flag; static JSClassRef global_class; +static std::shared_ptr global_constructor_data_mgr = nullptr; JSCCtx::JSCCtx(JSContextGroupRef group, std::weak_ptr vm): vm_(vm) { std::call_once(global_class_flag, []() { JSClassDefinition global = kJSClassDefinitionEmpty; global_class = JSClassCreate(&global); + global_constructor_data_mgr = std::make_shared(); }); context_ = JSGlobalContextCreateInGroup(group, global_class); @@ -67,7 +69,9 @@ JSCCtx::~JSCCtx() { JSGlobalContextRelease(context_); for (auto& [key, item] : constructor_data_holder_) { item->prototype = nullptr; - JSCVM::ClearConstructorDataPtr(item.get()); + if (global_constructor_data_mgr) { + global_constructor_data_mgr->ClearConstructorDataPtr(item.get()); + } } } @@ -260,7 +264,7 @@ std::shared_ptr JSCCtx::DefineClass(const string_view& name, if (!private_data) { return; } - if (!JSCVM::IsValidConstructorDataPtr(private_data)) { + if (!global_constructor_data_mgr || !global_constructor_data_mgr->IsValidConstructorDataPtr(private_data)) { return; } auto constructor_data = reinterpret_cast(private_data); @@ -965,7 +969,9 @@ void* JSCCtx::GetPrivateData(const std::shared_ptr& object) { } void JSCCtx::SaveConstructorData(std::unique_ptr constructor_data) { - JSCVM::SaveConstructorDataPtr(constructor_data.get()); + if (global_constructor_data_mgr) { + global_constructor_data_mgr->SaveConstructorDataPtr(constructor_data.get()); + } constructor_data_holder_[constructor_data->class_ref] = std::move(constructor_data); } diff --git a/driver/js/src/vm/jsc/jsc_vm.cc b/driver/js/src/vm/jsc/jsc_vm.cc index eceeb8d1a97..6e92f5c3d40 100644 --- a/driver/js/src/vm/jsc/jsc_vm.cc +++ b/driver/js/src/vm/jsc/jsc_vm.cc @@ -37,9 +37,6 @@ namespace hippy { inline namespace driver { inline namespace vm { -std::set JSCVM::constructor_data_ptr_set_; -std::mutex JSCVM::mutex_; - std::shared_ptr JSCVM::ParseJson(const std::shared_ptr& ctx, const string_view& json) { if (footstone::StringViewUtils::IsEmpty(json)) { return nullptr; @@ -93,21 +90,6 @@ JSStringRef JSCVM::CreateJSCString(const string_view& str_view) { return ret; } -void JSCVM::SaveConstructorDataPtr(void* ptr) { - std::lock_guard lock(mutex_); - constructor_data_ptr_set_.insert(ptr); -} - -void JSCVM::ClearConstructorDataPtr(void* ptr) { - std::lock_guard lock(mutex_); - constructor_data_ptr_set_.erase(ptr); -} - -bool JSCVM::IsValidConstructorDataPtr(void* ptr) { - std::lock_guard lock(mutex_); - return constructor_data_ptr_set_.find(ptr) != constructor_data_ptr_set_.end(); -} - } } }