Update CSSNodeFree for C#, Java and Objective-C
Summary: - Update CSSNodeFree to unlink parent and children for C#, Java and Objective-C bindings finalizer. - [C#] Fix build (Fix #232) - [C#] Add Clear API for convenience as CSSNodeFreeRecursive. - [C#] Revise and add unit tests Reviewed By: emilsjolander Differential Revision: D4069655 fbshipit-source-id: 1fd764059784d7968af38b6aaf7fb6f70fdee8ee
This commit is contained in:
committed by
Facebook Github Bot
parent
4d0e657653
commit
2168d68007
@@ -155,6 +155,17 @@ CSSNodeRef CSSNodeNew(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CSSNodeFree(const CSSNodeRef node) {
|
void CSSNodeFree(const CSSNodeRef node) {
|
||||||
|
if (node->parent) {
|
||||||
|
CSSNodeListDelete(node->parent->children, node);
|
||||||
|
node->parent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t childCount = CSSNodeChildCount(node);
|
||||||
|
for (uint32_t i = 0; i < childCount; i++) {
|
||||||
|
const CSSNodeRef child = CSSNodeGetChild(node, i);
|
||||||
|
child->parent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
CSSNodeListFree(node->children);
|
CSSNodeListFree(node->children);
|
||||||
free(node);
|
free(node);
|
||||||
gNodeInstanceCount--;
|
gNodeInstanceCount--;
|
||||||
|
@@ -15,7 +15,7 @@ using System.Text;
|
|||||||
|
|
||||||
namespace Facebook.CSSLayout
|
namespace Facebook.CSSLayout
|
||||||
{
|
{
|
||||||
public class CSSNode : IDisposable, IEnumerable<CSSNode>
|
public class CSSNode : IEnumerable<CSSNode>
|
||||||
{
|
{
|
||||||
private IntPtr _cssNode;
|
private IntPtr _cssNode;
|
||||||
|
|
||||||
@@ -35,7 +35,6 @@ namespace Facebook.CSSLayout
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException("Failed to allocate native memory");
|
throw new InvalidOperationException("Failed to allocate native memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~CSSNode()
|
~CSSNode()
|
||||||
@@ -483,6 +482,14 @@ namespace Facebook.CSSLayout
|
|||||||
Native.CSSNodeRemoveChild(_cssNode, child._cssNode);
|
Native.CSSNodeRemoveChild(_cssNode, child._cssNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
while (_children.Count > 0)
|
||||||
|
{
|
||||||
|
RemoveAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int IndexOf(CSSNode node)
|
public int IndexOf(CSSNode node)
|
||||||
{
|
{
|
||||||
return _children.IndexOf(node);
|
return _children.IndexOf(node);
|
||||||
|
@@ -52,117 +52,50 @@ namespace Facebook.CSSLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[ExpectedException("System.InvalidOperationException")]
|
public void TestReset()
|
||||||
public void TestAlreadyInitialize()
|
|
||||||
{
|
{
|
||||||
CSSNode node = new CSSNode();
|
|
||||||
node.Reinitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
[ExpectedException("System.InvalidOperationException")]
|
|
||||||
public void TestNullNativePointer()
|
|
||||||
{
|
|
||||||
CSSNode node = new CSSNode();
|
|
||||||
node.Free();
|
|
||||||
node.CalculateLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
[ExpectedException("System.InvalidOperationException")]
|
|
||||||
public void TestDoubleFree()
|
|
||||||
{
|
|
||||||
CSSNode node = new CSSNode();
|
|
||||||
node.Free();
|
|
||||||
node.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestReinitialize()
|
|
||||||
{
|
|
||||||
CSSNode node = new CSSNode();
|
|
||||||
node.Free();
|
|
||||||
node.Reinitialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
[ExpectedException("System.ObjectDisposedException")]
|
|
||||||
public void TestDisposed()
|
|
||||||
{
|
|
||||||
CSSNode node = new CSSNode();
|
|
||||||
node.Dispose();
|
|
||||||
node.CalculateLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestFree()
|
|
||||||
{
|
|
||||||
CSSNode node = new CSSNode();
|
|
||||||
node.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestDispose()
|
|
||||||
{
|
|
||||||
ForceGC();
|
|
||||||
int instanceCount = CSSNode.GetInstanceCount();
|
int instanceCount = CSSNode.GetInstanceCount();
|
||||||
CSSNode node = new CSSNode();
|
CSSNode node = new CSSNode();
|
||||||
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
node.Dispose();
|
node.Reset();
|
||||||
Assert.AreEqual(instanceCount, CSSNode.GetInstanceCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestDisposeWithUsing()
|
|
||||||
{
|
|
||||||
ForceGC();
|
|
||||||
int instanceCount = CSSNode.GetInstanceCount();
|
|
||||||
using (CSSNode node = new CSSNode())
|
|
||||||
{
|
|
||||||
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
}
|
}
|
||||||
Assert.AreEqual(instanceCount, CSSNode.GetInstanceCount());
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[ExpectedException("System.InvalidOperationException")]
|
[ExpectedException("System.InvalidOperationException")]
|
||||||
public void TestFreeParent()
|
public void TestResetParent()
|
||||||
{
|
{
|
||||||
CSSNode parent = new CSSNode();
|
CSSNode parent = new CSSNode();
|
||||||
CSSNode child = new CSSNode();
|
CSSNode child = new CSSNode();
|
||||||
parent.Insert(0, child);
|
parent.Insert(0, child);
|
||||||
parent.Free();
|
parent.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[ExpectedException("System.InvalidOperationException")]
|
[ExpectedException("System.InvalidOperationException")]
|
||||||
public void TestFreeChild()
|
public void TestResetChild()
|
||||||
{
|
{
|
||||||
CSSNode parent = new CSSNode();
|
CSSNode parent = new CSSNode();
|
||||||
CSSNode child = new CSSNode();
|
CSSNode child = new CSSNode();
|
||||||
parent.Insert(0, child);
|
parent.Insert(0, child);
|
||||||
child.Free();
|
child.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDisposeChild()
|
public void TestClear()
|
||||||
{
|
{
|
||||||
ForceGC();
|
|
||||||
int instanceCount = CSSNode.GetInstanceCount();
|
int instanceCount = CSSNode.GetInstanceCount();
|
||||||
CSSNode parent = new CSSNode();
|
CSSNode parent = new CSSNode();
|
||||||
CSSNode child0 = new CSSNode();
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
CSSNode child1 = new CSSNode();
|
CSSNode child = new CSSNode();
|
||||||
Assert.AreEqual(instanceCount + 3, CSSNode.GetInstanceCount());
|
|
||||||
Assert.AreEqual(0, parent.Count);
|
|
||||||
parent.Insert(0, child1);
|
|
||||||
Assert.AreEqual(0, parent.IndexOf(child1));
|
|
||||||
parent.Insert(0, child0);
|
|
||||||
Assert.AreEqual(0, parent.IndexOf(child0));
|
|
||||||
Assert.AreEqual(1, parent.IndexOf(child1));
|
|
||||||
child0.Dispose();
|
|
||||||
Assert.AreEqual(instanceCount + 2, CSSNode.GetInstanceCount());
|
Assert.AreEqual(instanceCount + 2, CSSNode.GetInstanceCount());
|
||||||
|
parent.Insert(0, child);
|
||||||
Assert.AreEqual(1, parent.Count);
|
Assert.AreEqual(1, parent.Count);
|
||||||
Assert.AreEqual(0, parent.IndexOf(child1));
|
Assert.AreEqual(parent, child.Parent);
|
||||||
|
parent.Clear();
|
||||||
|
Assert.AreEqual(0, parent.Count);
|
||||||
|
Assert.IsNull(child.Parent);
|
||||||
|
Assert.AreEqual(instanceCount + 2, CSSNode.GetInstanceCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -257,26 +190,48 @@ namespace Facebook.CSSLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDisposeParent()
|
public void TestParentDestructor()
|
||||||
{
|
{
|
||||||
ForceGC();
|
ForceGC();
|
||||||
int instanceCount = CSSNode.GetInstanceCount();
|
int instanceCount = CSSNode.GetInstanceCount();
|
||||||
CSSNode parent = new CSSNode();
|
CSSNode child = new CSSNode();
|
||||||
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
TestDisposeParentForGC(parent, instanceCount + 1);
|
|
||||||
|
TestParentDestructorForGC(child, instanceCount + 1);
|
||||||
ForceGC();
|
ForceGC();
|
||||||
Assert.AreEqual(instanceCount + 2, CSSNode.GetInstanceCount());
|
|
||||||
parent.Dispose();
|
Assert.IsNull(child.Parent);
|
||||||
ForceGC();
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
Assert.AreEqual(instanceCount, CSSNode.GetInstanceCount());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TestDisposeParentForGC(CSSNode parent, int instanceCount)
|
private void TestParentDestructorForGC(CSSNode child, int instanceCount)
|
||||||
|
{
|
||||||
|
CSSNode parent = new CSSNode();
|
||||||
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
|
parent.Insert(0, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestClearWithChildDestructor()
|
||||||
|
{
|
||||||
|
ForceGC();
|
||||||
|
int instanceCount = CSSNode.GetInstanceCount();
|
||||||
|
CSSNode node = new CSSNode();
|
||||||
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
|
TestClearWithChildDestructorForGC(node, instanceCount + 1);
|
||||||
|
ForceGC();
|
||||||
|
Assert.AreEqual(instanceCount + 2, CSSNode.GetInstanceCount());
|
||||||
|
node.Clear();
|
||||||
|
Assert.AreEqual(0, node.Count);
|
||||||
|
ForceGC();
|
||||||
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TestClearWithChildDestructorForGC(CSSNode parent, int instanceCount)
|
||||||
{
|
{
|
||||||
CSSNode child = new CSSNode();
|
CSSNode child = new CSSNode();
|
||||||
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
Assert.AreEqual(instanceCount + 1, CSSNode.GetInstanceCount());
|
||||||
parent.Insert(0, child);
|
parent.Insert(0, child);
|
||||||
child = null;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user