]> git.kaiwu.me - njs.git/commitdiff
XML: fixed exception classes
authorDmitry Volyntsev <xeioex@nginx.com>
Wed, 3 Jun 2026 02:07:15 +0000 (19:07 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Wed, 3 Jun 2026 21:34:17 +0000 (14:34 -0700)
Report XML API misuse as TypeError and XML parse failures as SyntaxError,
aligning njs and QuickJS behavior.

The QuickJS message "'this' is not XMLNode or XMLDoc" is changed to
"value is not XMLNode or XMLDoc" because qjs_xml_node() is not always
validating this.

external/njs_xml_module.c
external/qjs_xml_module.c
test/xml/xml.t.mjs

index f1d275aa3f1015ef4494135708f9a9c1d08f2d92..4736c3ac1f696ccfda486447dc4fb106915e6517 100644 (file)
@@ -2022,7 +2022,7 @@ njs_xml_error(njs_vm_t *vm, njs_xml_doc_t *current, const char *fmt, ...)
                         err->int2);
     }
 
-    njs_vm_error(vm, "%*s", p - errstr, errstr);
+    njs_vm_syntax_error(vm, "%*s", p - errstr, errstr);
 }
 
 
index af297e5be088bfcff24bdc06f968f241022e1829..36dfdba8027bb79652647836400e575e45123b4b 100644 (file)
@@ -384,7 +384,7 @@ qjs_xml_doc_get_own_property(JSContext *cx, JSPropertyDescriptor *pdesc,
 
     tree = JS_GetOpaque(obj, QJS_CORE_CLASS_ID_XML_DOC);
     if (tree == NULL) {
-        (void) JS_ThrowInternalError(cx, "\"this\" is not an XMLDoc");
+        (void) JS_ThrowTypeError(cx, "\"this\" is not an XMLDoc");
         return -1;
     }
 
@@ -469,7 +469,7 @@ qjs_xml_doc_get_own_property_names(JSContext *cx, JSPropertyEnum **ptab,
 
     tree = JS_GetOpaque(obj, QJS_CORE_CLASS_ID_XML_DOC);
     if (tree == NULL) {
-        (void) JS_ThrowInternalError(cx, "\"this\" is not an XMLDoc");
+        (void) JS_ThrowTypeError(cx, "\"this\" is not an XMLDoc");
         return -1;
     }
 
@@ -741,9 +741,9 @@ qjs_xml_node_tag_modify(JSContext *cx, JSValue obj, njs_str_t *name,
     }
 
     if (!JS_IsNullOrUndefined(setval)) {
-        JS_ThrowInternalError(cx, "XMLNode.$tag$xxx is not assignable, "
-                           "use addChild() or node.$tags = [node1, node2, ..] "
-                           "syntax");
+        JS_ThrowTypeError(cx, "XMLNode.$tag$xxx is not assignable, "
+                          "use addChild() or node.$tags = [node1, node2, ..] "
+                          "syntax");
         return -1;
     }
 
@@ -929,7 +929,7 @@ qjs_xml_node_get_own_property(JSContext *cx, JSPropertyDescriptor *pdesc,
 
     current = JS_GetOpaque(obj, QJS_CORE_CLASS_ID_XML_NODE);
     if (current == NULL) {
-        (void) JS_ThrowInternalError(cx, "\"this\" is not an XMLNode");
+        (void) JS_ThrowTypeError(cx, "\"this\" is not an XMLNode");
         return -1;
     }
 
@@ -1173,7 +1173,7 @@ qjs_xml_node_get_own_property_names(JSContext *cx, JSPropertyEnum **ptab,
 
     tree = JS_GetOpaque(obj, QJS_CORE_CLASS_ID_XML_NODE);
     if (tree == NULL) {
-        (void) JS_ThrowInternalError(cx, "\"this\" is not an XMLNode");
+        (void) JS_ThrowTypeError(cx, "\"this\" is not an XMLNode");
         return -1;
     }
 
@@ -1552,7 +1552,7 @@ qjs_xml_node(JSContext *cx, JSValueConst val, xmlDoc **doc)
     if (current == NULL) {
         tree = JS_GetOpaque(val, QJS_CORE_CLASS_ID_XML_DOC);
         if (tree == NULL) {
-            JS_ThrowInternalError(cx, "'this' is not XMLNode or XMLDoc");
+            JS_ThrowTypeError(cx, "value is not XMLNode or XMLDoc");
             return NULL;
         }
 
@@ -1611,7 +1611,7 @@ qjs_xml_attr_get_own_property(JSContext *cx, JSPropertyDescriptor *pdesc,
 
     current = JS_GetOpaque(obj, QJS_CORE_CLASS_ID_XML_ATTR);
     if (current == NULL) {
-        (void) JS_ThrowInternalError(cx, "\"this\" is not an XMLAttr");
+        (void) JS_ThrowTypeError(cx, "\"this\" is not an XMLAttr");
         return -1;
     }
 
@@ -1675,7 +1675,7 @@ qjs_xml_attr_get_own_property_names(JSContext *cx, JSPropertyEnum **ptab,
 
     current = JS_GetOpaque(obj, QJS_CORE_CLASS_ID_XML_ATTR);
     if (current == NULL) {
-        (void) JS_ThrowInternalError(cx, "\"this\" is not an XMLAttr");
+        (void) JS_ThrowTypeError(cx, "\"this\" is not an XMLAttr");
         return -1;
     }
 
index 4533c8adad36a9be28caaf611d99da96d84ab978..8590bddc97a43ec1a45cde4fdde48411860b3aeb 100644 (file)
@@ -366,6 +366,18 @@ let modify_tsuite = {
             return xml.serializeToString(doc);
           },
           expected: `<note><to a="foo" b="bar">Tove</to><from>Jani</from></note>` },
+        { get: (doc) => {
+            try {
+                doc.note.$tag$xxx = doc.note.to;
+            } catch (e) {
+                if (e instanceof TypeError) {
+                    return 'OK';
+                }
+            }
+
+            throw Error('unexpected exception');
+          },
+          expected: 'OK' },
         { doc: `<root><a>A</a><b>B</b><a>C</a></root>`,
           get: (doc) => {
             doc.$root.removeChildren('a');