]> git.kaiwu.me - njs.git/commitdiff
XML: fixed XMLNode update.
authorDmitry Volyntsev <xeioex@nginx.com>
Sat, 22 Nov 2025 01:41:53 +0000 (17:41 -0800)
committerDmitry Volyntsev <xeioexception@gmail.com>
Tue, 25 Nov 2025 23:36:16 +0000 (15:36 -0800)
external/njs_xml_module.c
external/qjs_xml_module.c
test/xml/xml.t.mjs

index 2438223870c674098e3d5c5fc45d6d840b9d4dcb..f1d275aa3f1015ef4494135708f9a9c1d08f2d92 100644 (file)
@@ -96,11 +96,11 @@ static njs_int_t njs_xml_node_ext_text(njs_vm_t *vm, njs_object_prop_t *prop,
 
 static njs_int_t njs_xml_node_attr_handler(njs_vm_t *vm, xmlNode *current,
     njs_str_t *name, njs_value_t *setval, njs_value_t *retval);
-static njs_int_t njs_xml_node_tag_remove(njs_vm_t *vm, xmlNode *current,
+static njs_int_t njs_xml_node_tag_remove(njs_vm_t *vm, njs_value_t *value,
     njs_str_t *name);
-static njs_int_t njs_xml_node_tag_handler(njs_vm_t *vm, xmlNode *current,
+static njs_int_t njs_xml_node_tag_handler(njs_vm_t *vm, njs_value_t *value,
     njs_str_t *name, njs_value_t *setval, njs_value_t *retval);
-static njs_int_t njs_xml_node_tags_handler(njs_vm_t *vm, xmlNode *current,
+static njs_int_t njs_xml_node_tags_handler(njs_vm_t *vm, njs_value_t *value,
     njs_str_t *name, njs_value_t *setval, njs_value_t *retval);
 
 static xmlNode *njs_xml_external_node(njs_vm_t *vm, njs_value_t *value);
@@ -110,7 +110,7 @@ static const u_char *njs_xml_value_to_c_string(njs_vm_t *vm, njs_value_t *value,
     u_char *dst, size_t size);
 static njs_int_t njs_xml_encode_special_chars(njs_vm_t *vm, njs_str_t *src,
     njs_str_t *out);
-static njs_int_t njs_xml_replace_node(njs_vm_t *vm, xmlNode *old,
+static njs_int_t njs_xml_replace_node(njs_vm_t *vm, njs_value_t *value,
     xmlNode *current);
 static void njs_xml_node_cleanup(void *data);
 static void njs_xml_doc_cleanup(void *data);
@@ -706,7 +706,7 @@ njs_xml_node_ext_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop,
             name.length -= njs_length("$tag$");
             name.start += njs_length("$tag$");
 
-            return njs_xml_node_tag_handler(vm, current, &name, setval, retval);
+            return njs_xml_node_tag_handler(vm, value, &name, setval, retval);
         }
 
         if (name.length >= njs_length("$tags$")
@@ -715,12 +715,11 @@ njs_xml_node_ext_prop_handler(njs_vm_t *vm, njs_object_prop_t *prop,
             name.length -= njs_length("$tags$");
             name.start += njs_length("$tags$");
 
-            return njs_xml_node_tags_handler(vm, current, &name, setval,
-                                             retval);
+            return njs_xml_node_tags_handler(vm, value, &name, setval, retval);
         }
     }
 
-    return njs_xml_node_tag_handler(vm, current, &name, setval, retval);
+    return njs_xml_node_tag_handler(vm, value, &name, setval, retval);
 }
 
 
@@ -770,7 +769,7 @@ njs_xml_node_ext_add_child(njs_vm_t *vm, njs_value_t *args,
 
     njs_value_undefined_set(retval);
 
-    return njs_xml_replace_node(vm, current, copy);
+    return njs_xml_replace_node(vm, njs_argument(args, 0), copy);
 
 error:
 
@@ -909,7 +908,7 @@ njs_xml_node_ext_remove_children(njs_vm_t *vm, njs_value_t *args,
 
         njs_value_string_get(vm, selector, &name);
 
-        return njs_xml_node_tag_remove(vm, current, &name);
+        return njs_xml_node_tag_remove(vm, njs_argument(args, 0), &name);
     }
 
     /* all. */
@@ -925,7 +924,7 @@ njs_xml_node_ext_remove_children(njs_vm_t *vm, njs_value_t *args,
         copy->children = NULL;
     }
 
-    return njs_xml_replace_node(vm, current, copy);
+    return njs_xml_replace_node(vm, njs_argument(args, 0), copy);
 }
 
 
@@ -990,7 +989,7 @@ njs_xml_node_ext_tags(njs_vm_t *vm, njs_object_prop_t *prop, uint32_t unused,
     name.start = NULL;
     name.length = 0;
 
-    return njs_xml_node_tags_handler(vm, current, &name, setval, retval);
+    return njs_xml_node_tags_handler(vm, value, &name, setval, retval);
 }
 
 
@@ -1051,7 +1050,7 @@ njs_xml_node_ext_text(njs_vm_t *vm, njs_object_prop_t *unused, uint32_t unused1,
         njs_value_undefined_set(retval);
     }
 
-    return njs_xml_replace_node(vm, current, copy);
+    return njs_xml_replace_node(vm, value, copy);
 }
 
 
@@ -1143,11 +1142,12 @@ njs_xml_node_attr_handler(njs_vm_t *vm, xmlNode *current, njs_str_t *name,
 
 
 static njs_int_t
-njs_xml_node_tag_remove(njs_vm_t *vm, xmlNode *current, njs_str_t *name)
+njs_xml_node_tag_remove(njs_vm_t *vm, njs_value_t *value, njs_str_t *name)
 {
     size_t     size;
-    xmlNode    *node, *next, *copy;
-    njs_int_t  ret;
+    xmlNode    *current, *node, *next, *copy;
+
+    current = njs_vm_external(vm, njs_xml_node_proto_id, value);
 
     copy = xmlDocCopyNode(current, current->doc, 1);
     if (njs_slow_path(copy == NULL)) {
@@ -1170,23 +1170,22 @@ njs_xml_node_tag_remove(njs_vm_t *vm, xmlNode *current, njs_str_t *name)
             continue;
         }
 
-        ret = njs_xml_replace_node(vm, node, NULL);
-        if (njs_slow_path(ret != NJS_OK)) {
-            xmlFreeNode(copy);
-            return NJS_ERROR;
-        }
+        xmlUnlinkNode(node);
+        xmlFreeNode(node);
     }
 
-    return njs_xml_replace_node(vm, current, copy);
+    return njs_xml_replace_node(vm, value, copy);
 }
 
 
 static njs_int_t
-njs_xml_node_tag_handler(njs_vm_t *vm, xmlNode *current, njs_str_t *name,
+njs_xml_node_tag_handler(njs_vm_t *vm, njs_value_t *value, njs_str_t *name,
     njs_value_t *setval, njs_value_t *retval)
 {
     size_t   size;
-    xmlNode  *node;
+    xmlNode  *current, *node;
+
+    current = njs_vm_external(vm, njs_xml_node_proto_id, value);
 
     if (retval != NULL && setval == NULL) {
 
@@ -1223,21 +1222,23 @@ njs_xml_node_tag_handler(njs_vm_t *vm, xmlNode *current, njs_str_t *name,
 
     /* delete. */
 
-    return njs_xml_node_tag_remove(vm, current, name);
+    return njs_xml_node_tag_remove(vm, value, name);
 }
 
 
 static njs_int_t
-njs_xml_node_tags_handler(njs_vm_t *vm, xmlNode *current, njs_str_t *name,
+njs_xml_node_tags_handler(njs_vm_t *vm, njs_value_t *value, njs_str_t *name,
     njs_value_t *setval, njs_value_t *retval)
 {
     size_t       size;
     int64_t      i, length;
-    xmlNode      *node, *rnode, *copy;
+    xmlNode      *current, *node, *rnode, *copy;
     njs_int_t    ret;
     njs_value_t  *push;
     njs_opaque_value_t  *start;
 
+    current = njs_vm_external(vm, njs_xml_node_proto_id, value);
+
     if (retval != NULL && setval == NULL) {
 
         /* get. */
@@ -1294,7 +1295,7 @@ njs_xml_node_tags_handler(njs_vm_t *vm, xmlNode *current, njs_str_t *name,
 
     if (retval == NULL) {
         /* delete. */
-        return njs_xml_replace_node(vm, current, copy);
+        return njs_xml_replace_node(vm, value, copy);
     }
 
     if (!njs_value_is_array(setval)) {
@@ -1338,7 +1339,7 @@ njs_xml_node_tags_handler(njs_vm_t *vm, xmlNode *current, njs_str_t *name,
 
     njs_value_undefined_set(retval);
 
-    return njs_xml_replace_node(vm, current, copy);
+    return njs_xml_replace_node(vm, value, copy);
 
 error:
 
@@ -1512,9 +1513,12 @@ njs_xml_encode_special_chars(njs_vm_t *vm, njs_str_t *src, njs_str_t *out)
 
 
 static njs_int_t
-njs_xml_replace_node(njs_vm_t *vm, xmlNode *old, xmlNode *current)
+njs_xml_replace_node(njs_vm_t *vm, njs_value_t *value, xmlNode *current)
 {
-    njs_mp_cleanup_t  *cln;
+    xmlNode          *old;
+    njs_mp_cleanup_t *cln;
+
+    old = njs_vm_external(vm, njs_xml_node_proto_id, value);
 
     if (current != NULL) {
         old = xmlReplaceNode(old, current);
@@ -1523,6 +1527,8 @@ njs_xml_replace_node(njs_vm_t *vm, xmlNode *old, xmlNode *current)
         xmlUnlinkNode(old);
     }
 
+    njs_value_external_set(value, current);
+
     cln = njs_mp_cleanup_add(njs_vm_memory_pool(vm), 0);
     if (njs_slow_path(cln == NULL)) {
         njs_vm_memory_error(vm);
index 274eaec000bfadfac7c8e0a13bdd8c9d5bb76d4f..af297e5be088bfcff24bdc06f968f241022e1829 100644 (file)
@@ -2032,6 +2032,8 @@ qjs_xml_replace_node(JSContext *cx, qjs_xml_node_t *node, xmlNode *current)
         xmlUnlinkNode(old);
     }
 
+    node->node = current;
+
     old->next = node->doc->free;
     node->doc->free = old;
 }
index 51d80217152732310e29a2f141028e07af3e8a6b..4533c8adad36a9be28caaf611d99da96d84ab978 100644 (file)
@@ -165,6 +165,25 @@ let modify_tsuite = {
             return doc.note.$text;
           },
           expected: 'WAKA' },
+        { get: (doc) => {
+            doc.note.setText('WAKA');
+            doc.note.setText('OVERWRITE');
+            return doc.note.$text;
+          },
+          expected: 'OVERWRITE' },
+        { get: (doc) => {
+            let note = doc.note;
+            note.setText('WAKA');
+            note.setText('OVERWRITE');
+            return note.$text;
+          },
+          expected: 'OVERWRITE' },
+        { get: (doc) => {
+            let note = doc.note;
+            note.setText('WAKA');
+            return doc.note.$text;
+          },
+          expected: 'WAKA' },
         { get: (doc) => {
             doc.note.setText('WAKA');
             return xml.serializeToString(doc);
@@ -321,6 +340,12 @@ let modify_tsuite = {
             return xml.serializeToString(doc);
           },
           expected: `<note><from>Jani</from></note>` },
+        { get: (doc) => {
+            let note = doc.note;
+            note.removeChildren('to');
+            return xml.serializeToString(doc);
+          },
+          expected: `<note><from>Jani</from></note>` },
         { get: (doc) => {
             delete doc.note.$tag$to;
             return xml.serializeToString(doc);