Files
bun.sh/src/bun.js/bindings/YogaNodeImpl.cpp
Claude Bot 07fa3909ea Complete RefCounted migration for both JSYogaNode and JSYogaConfig
- Migrated JSYogaNode to use RefCounted<YogaNodeImpl> pattern
- Migrated JSYogaConfig to use RefCounted<YogaConfigImpl> pattern
- Both JS wrappers now use impl() and do minimal work
- Implemented proper opaque root GC lifecycle management
- Added WeakHandleOwner with finalize() that derefs C++ wrappers
- Updated all API calls to use impl().yogaNode() / impl().yogaConfig()

The core RefCounted architecture is complete. Some compilation issues remain
that need header includes and method name fixes.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-30 05:04:06 +00:00

81 lines
1.9 KiB
C++

#include "YogaNodeImpl.h"
#include "JSYogaNode.h"
#include "JSYogaConfig.h"
#include "JSYogaNodeOwner.h"
#include <yoga/Yoga.h>
namespace Bun {
Ref<YogaNodeImpl> YogaNodeImpl::create(YGConfigRef config, JSYogaConfig* jsConfig)
{
return adoptRef(*new YogaNodeImpl(config, jsConfig));
}
YogaNodeImpl::YogaNodeImpl(YGConfigRef config, JSYogaConfig* jsConfig)
: m_jsConfig(jsConfig)
{
if (config) {
m_yogaNode = YGNodeNewWithConfig(config);
} else {
m_yogaNode = YGNodeNew();
}
// Store this C++ wrapper in the Yoga node's context
YGNodeSetContext(m_yogaNode, this);
}
YogaNodeImpl::~YogaNodeImpl()
{
if (m_yogaNode) {
// Clear the context pointer to avoid callbacks during cleanup
YGNodeSetContext(m_yogaNode, nullptr);
// Remove from parent to avoid use-after-free when parent tries to clear owner
YGNodeRef parent = YGNodeGetParent(m_yogaNode);
if (parent) {
YGNodeRemoveChild(parent, m_yogaNode);
}
YGNodeFree(m_yogaNode);
m_yogaNode = nullptr;
}
}
void YogaNodeImpl::setJSWrapper(JSYogaNode* wrapper)
{
// Increment ref count for the weak handle context
this->ref();
// Create weak reference with our JS owner
m_wrapper = JSC::Weak<JSYogaNode>(wrapper, &jsYogaNodeOwner(), this);
}
void YogaNodeImpl::clearJSWrapper()
{
m_wrapper.clear();
}
JSYogaNode* YogaNodeImpl::jsWrapper() const
{
return m_wrapper.get();
}
YogaNodeImpl* YogaNodeImpl::fromYGNode(YGNodeRef nodeRef)
{
if (!nodeRef) return nullptr;
return static_cast<YogaNodeImpl*>(YGNodeGetContext(nodeRef));
}
void YogaNodeImpl::replaceYogaNode(YGNodeRef newNode)
{
if (m_yogaNode) {
YGNodeSetContext(m_yogaNode, nullptr);
YGNodeFree(m_yogaNode);
}
m_yogaNode = newNode;
if (newNode) {
YGNodeSetContext(newNode, this);
}
}
} // namespace Bun