git » sdk » commit c6d8a3b

Save on allocations for TextNode

author Stephen Paul Weber
2025-06-24 18:12:59 UTC
committer Stephen Paul Weber
2025-06-24 18:12:59 UTC
parent da7fa0f558d2e6e3b4e09e993680bd0410786244

Save on allocations for TextNode

Just use an abstract over a String most of the time, and only allocate
when we're actually doing polymorphism. Based on profiling of the
XEP0393 parser

snikket/Stanza.hx +37 -8

diff --git a/snikket/Stanza.hx b/snikket/Stanza.hx
index 27b345e..8563f32 100644
--- a/snikket/Stanza.hx
+++ b/snikket/Stanza.hx
@@ -18,19 +18,24 @@ private interface NodeInterface {
 	public function traverse(f: (Stanza)->Bool):NodeInterface;
 }
 
-class TextNode implements NodeInterface {
-	public var content(default, null):String = "";
+class TextNodeClass implements NodeInterface {
+	public var content(get, never):String;
+	private final node: TextNode;
 
-	public function new (content:String) {
-		this.content = content;
+	public function new(node: TextNode) {
+		this.node = node;
+	}
+
+	private function get_content(): String {
+		return node.content;
 	}
 
 	public function serialize():String {
-		return Util.xmlEscape(content);
+		return node.serialize();
 	}
 
-	public function clone():TextNode {
-		return new TextNode(this.content);
+	public function clone():TextNodeClass {
+		return this;
 	}
 
 	public function traverse(f: (Stanza)->Bool) {
@@ -38,6 +43,30 @@ class TextNode implements NodeInterface {
 	}
 }
 
+abstract TextNode(String) {
+	public var content(get, never):String;
+
+	inline public function new(content:String) {
+		this = content;
+	}
+
+	inline private function get_content(): String {
+		return this;
+	}
+
+	inline public function serialize():String {
+		return Util.xmlEscape(this);
+	}
+
+	inline public function clone():TextNode {
+		return new TextNode(this);
+	}
+
+	inline public function toClass() {
+		return new TextNodeClass(new TextNode(this));
+	}
+}
+
 class StanzaError {
 	public var type:String;
 	public var condition:String;
@@ -225,7 +254,7 @@ class Stanza implements NodeInterface {
 	public function getChildren():Array<NodeInterface> {
 		return children.map(child -> switch(child) {
 			case Element(el): el;
-			case CData(text): text;
+			case CData(text): text.toClass();
 		});
 	}