diff --git a/CSSLayout/CSSLayout.c b/CSSLayout/CSSLayout.c
index ba1b10c6..76f37349 100644
--- a/CSSLayout/CSSLayout.c
+++ b/CSSLayout/CSSLayout.c
@@ -219,6 +219,7 @@ void _CSSNodeMarkDirty(const CSSNodeRef node) {
}
void CSSNodeInsertChild(const CSSNodeRef node, const CSSNodeRef child, const uint32_t index) {
+ CSS_ASSERT(child->parent == NULL, "Child already has a parent, it must be removed first.");
CSSNodeListInsert(node->children, child, index);
child->parent = node;
_CSSNodeMarkDirty(node);
@@ -2295,3 +2296,17 @@ void CSSNodeCalculateLayout(const CSSNodeRef node,
}
}
}
+
+#ifdef CSS_ASSERT_FAIL_ENABLED
+static CSSAssertFailFunc gAssertFailFunc;
+
+void CSSAssertSetFailFunc(CSSAssertFailFunc func) {
+ gAssertFailFunc = func;
+}
+
+void CSSAssertFail(const char *message) {
+ if (gAssertFailFunc) {
+ (*gAssertFailFunc)(message);
+ }
+}
+#endif
diff --git a/CSSLayout/CSSLayout.h b/CSSLayout/CSSLayout.h
index ea532bbb..9c4a1012 100644
--- a/CSSLayout/CSSLayout.h
+++ b/CSSLayout/CSSLayout.h
@@ -122,6 +122,10 @@ typedef CSSSize (*CSSMeasureFunc)(void *context,
CSSMeasureMode heightMode);
typedef void (*CSSPrintFunc)(void *context);
+#ifdef CSS_ASSERT_FAIL_ENABLED
+typedef void (*CSSAssertFailFunc)(const char *message);
+#endif
+
// CSSNode
WIN_EXPORT CSSNodeRef CSSNodeNew();
WIN_EXPORT void CSSNodeInit(const CSSNodeRef node);
@@ -206,4 +210,10 @@ CSS_NODE_LAYOUT_PROPERTY(float, Width);
CSS_NODE_LAYOUT_PROPERTY(float, Height);
CSS_NODE_LAYOUT_PROPERTY(CSSDirection, Direction);
+#ifdef CSS_ASSERT_FAIL_ENABLED
+// Assert
+WIN_EXPORT void CSSAssertSetFailFunc(CSSAssertFailFunc func);
+WIN_EXPORT void CSSAssertFail(const char *message);
+#endif
+
CSS_EXTERN_C_END
diff --git a/CSSLayout/CSSMacros.h b/CSSLayout/CSSMacros.h
index f4e29a1e..b9b1faad 100644
--- a/CSSLayout/CSSMacros.h
+++ b/CSSLayout/CSSMacros.h
@@ -33,8 +33,16 @@
#define CSS_ABORT()
#endif
-#define CSS_ASSERT(X, message) \
- if (!(X)) { \
- fprintf(stderr, "%s\n", message); \
- CSS_ABORT(); \
+#if CSS_ASSERT_FAIL_ENABLED
+#define CSS_ERROR_FUNC(message) CSSAssertFail(message)
+#else
+#define CSS_ERROR_FUNC(message) fprintf(stderr, "%s", message)
+#endif
+
+#ifndef CSS_ASSERT
+#define CSS_ASSERT(X, message) \
+ if (!(X)) { \
+ CSS_ERROR_FUNC(message); \
+ CSS_ABORT(); \
}
+#endif
diff --git a/csharp/CSSLayout/CSSLayout.vcxproj b/csharp/CSSLayout/CSSLayout.vcxproj
old mode 100644
new mode 100755
index 5f2e34f0..1037691d
--- a/csharp/CSSLayout/CSSLayout.vcxproj
+++ b/csharp/CSSLayout/CSSLayout.vcxproj
@@ -87,7 +87,7 @@
Level3
Disabled
- WIN32;_DEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;CSS_ASSERT_FAIL_ENABLED;FB_ASSERTIONS_ENABLED=0;%(PreprocessorDefinitions)
true
@@ -101,7 +101,7 @@
Level3
Disabled
- _DEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;%(PreprocessorDefinitions)
+ _DEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;CSS_ASSERT_FAIL_ENABLED;FB_ASSERTIONS_ENABLED=0;%(PreprocessorDefinitions)
true
@@ -117,7 +117,7 @@
MaxSpeed
true
true
- WIN32;NDEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;CSS_ASSERT_FAIL_ENABLED;FB_ASSERTIONS_ENABLED=0;%(PreprocessorDefinitions)
true
@@ -135,7 +135,7 @@
MaxSpeed
true
true
- NDEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;%(PreprocessorDefinitions)
+ NDEBUG;_WINDOWS;_USRDLL;CSSLAYOUT_EXPORTS;CSS_ASSERT_FAIL_ENABLED;FB_ASSERTIONS_ENABLED=0;%(PreprocessorDefinitions)
true
@@ -174,4 +174,4 @@
-
\ No newline at end of file
+
diff --git a/csharp/Facebook.CSSLayout/CSSAssert.cs b/csharp/Facebook.CSSLayout/CSSAssert.cs
new file mode 100644
index 00000000..adb0aada
--- /dev/null
+++ b/csharp/Facebook.CSSLayout/CSSAssert.cs
@@ -0,0 +1,31 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
+using System;
+
+namespace Facebook.CSSLayout
+{
+ internal static class CSSAssert
+ {
+ public delegate void FailFunc(string message);
+
+ private static bool _assertInitialized;
+
+ public static void Initialize()
+ {
+ if (!_assertInitialized)
+ {
+ Native.CSSAssertSetFailFunc((message) => {
+ throw new InvalidOperationException(message);
+ });
+ _assertInitialized = true;
+ }
+ }
+ }
+}
diff --git a/csharp/Facebook.CSSLayout/CSSNode.cs b/csharp/Facebook.CSSLayout/CSSNode.cs
index 1f941fe5..d344eccc 100644
--- a/csharp/Facebook.CSSLayout/CSSNode.cs
+++ b/csharp/Facebook.CSSLayout/CSSNode.cs
@@ -93,6 +93,7 @@ namespace Facebook.CSSLayout
throw new InvalidOperationException("Allready initialized node");
}
+ CSSAssert.Initialize();
_cssNode = Native.CSSNodeNew();
_children = new List(4);
Native.CSSNodeSetPrintFunc(_cssNode, _printFunc);
diff --git a/csharp/Facebook.CSSLayout/Native.cs b/csharp/Facebook.CSSLayout/Native.cs
index 8546d32d..90d387ef 100644
--- a/csharp/Facebook.CSSLayout/Native.cs
+++ b/csharp/Facebook.CSSLayout/Native.cs
@@ -20,6 +20,9 @@ namespace Facebook.CSSLayout
private const string DllName = "CSSLayout";
#endif
+ [DllImport(DllName)]
+ public static extern void CSSAssertSetFailFunc(CSSAssert.FailFunc func);
+
[DllImport(DllName)]
public static extern IntPtr CSSNodeNew();
diff --git a/tests/csharp/Facebook.CSSLayout/CSSNodeTest.cs b/tests/csharp/Facebook.CSSLayout/CSSNodeTest.cs
index 0edc1904..f248d492 100644
--- a/tests/csharp/Facebook.CSSLayout/CSSNodeTest.cs
+++ b/tests/csharp/Facebook.CSSLayout/CSSNodeTest.cs
@@ -41,6 +41,21 @@ namespace Facebook.CSSLayout
Assert.AreEqual(0, parent.Count);
}
+ [Test]
+ [ExpectedException("System.InvalidOperationException")]
+ public void TestCannotAddChildToMultipleParents()
+ {
+ CSSNode parent1 = new CSSNode();
+ parent1.Initialize();
+ CSSNode parent2 = new CSSNode();
+ parent2.Initialize();
+ CSSNode child = new CSSNode();
+ child.Initialize();
+
+ parent1.Insert(0, child);
+ parent2.Insert(0, child);
+ }
+
[Test]
[ExpectedException("System.InvalidOperationException")]
public void TestAlreadyInitialize()