Add JavaScript test for CJX_Node object.

Check return from XFA_GetElementByName() for XFA_Element::Unknown
to avoid asserts in debug builds as uncovered by tests.

Change-Id: I885b086b0e276dbda890f11c47fd65e9a4882bbc
Reviewed-on: https://pdfium-review.googlesource.com/c/50293
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fxjs/xfa/cjx_node.cpp b/fxjs/xfa/cjx_node.cpp
index 4997f23..98bf510 100644
--- a/fxjs/xfa/cjx_node.cpp
+++ b/fxjs/xfa/cjx_node.cpp
@@ -210,8 +210,11 @@
 
   WideString expression = runtime->ToWideString(params[0]);
   int32_t iValue = params.size() >= 2 ? runtime->ToInt32(params[1]) : 0;
-  CXFA_Node* pNode = GetOrCreateProperty<CXFA_Node>(
-      iValue, XFA_GetElementByName(expression.AsStringView()));
+  XFA_Element eElement = XFA_GetElementByName(expression.AsStringView());
+  if (eElement == XFA_Element::Unknown)
+    return CJS_Result::Success(runtime->NewNull());
+
+  CXFA_Node* pNode = GetOrCreateProperty<CXFA_Node>(iValue, eElement);
   if (!pNode)
     return CJS_Result::Success(runtime->NewNull());
 
@@ -236,9 +239,12 @@
   if (attr.has_value() && HasAttribute(attr.value().attribute))
     return CJS_Result::Success(runtime->NewBoolean(true));
 
+  XFA_Element eType = XFA_GetElementByName(expression.AsStringView());
+  if (eType == XFA_Element::Unknown)
+    return CJS_Result::Success(runtime->NewBoolean(false));
+
   bool bParent = params.size() < 2 || runtime->ToBoolean(params[1]);
   int32_t iIndex = params.size() == 3 ? runtime->ToInt32(params[2]) : 0;
-  XFA_Element eType = XFA_GetElementByName(expression.AsStringView());
   bool bHas = !!GetOrCreateProperty<CXFA_Node>(iIndex, eType);
   if (!bHas && bParent && GetXFANode()->GetParent()) {
     // Also check on the parent.
diff --git a/testing/resources/javascript/xfa_specific/xfa_node.in b/testing/resources/javascript/xfa_specific/xfa_node.in
new file mode 100644
index 0000000..d4620c0
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/xfa_node.in
@@ -0,0 +1,81 @@
+{{header}}
+{{include ../../xfa_catalog_1_0.fragment}}
+{{include ../../xfa_object_2_0.fragment}}
+{{include ../../xfa_preamble_3_0.fragment}}
+{{include ../../xfa_config_4_0.fragment}}
+{{object 5 0}} <<
+>>
+stream
+<template>
+  <subform layout="tb" name="my_doc">
+    <pageSet id="page" relation="orderedOccurrence">
+      <occur initial="1" max="1" min="1"/>
+      <pageArea id="Page1" name="Page1">
+        <occur max="1" min="1"/>
+        <contentArea h="100mm" w="200mm" x="0.25in" y="0.25in"/>
+      </pageArea>
+      <pageArea id="Page2" name="Page2">
+        <occur max="1" min="1"/>
+        <contentArea h="100mm" w="200mm" x="0.25in" y="0.25in"/>
+      </pageArea>
+    </pageSet>
+    <event activity="docReady" ref="$host">
+      <script contentType="application/x-javascript">
+        {{include ../expect.js}}
+        {{include ../property_test_helpers.js}}
+        testROProperty(my_doc, "isContainer", true);
+        testROProperty(my_doc, "isNull", false);
+        testROProperty(my_doc, "model", "[object XFAObject]");
+        testROProperty(my_doc, "ns", "");
+        testROProperty(my_doc, "oneOfChild", false);
+        expect("typeof my_doc.applyXSL", "function");
+        expect("typeof my_doc.assignNode", "function");
+        expect("typeof my_doc.clone", "function");
+        expect("typeof my_doc.getAttribute", "function");
+        expect("typeof my_doc.getElement", "function");
+        expect("typeof my_doc.isPropertySpecified", "function");
+        expect("typeof my_doc.loadXML", "function");
+        expect("typeof my_doc.saveFilteredXML", "function");
+        expect("typeof my_doc.saveXML", "function");
+        expect("typeof my_doc.setAttribute", "function");
+        expect("typeof my_doc.setElement", "function");
+        expectError("my_doc.applyXSL()");
+        expect("my_doc.applyXSL(42)", undefined);
+        expectError("my_doc.assignNode()");
+        expect("my_doc.assignNode(42)", undefined);
+        expectError("my_doc.clone()");
+        expect("my_doc.clone(true)", "[object XFAObject]");
+        expect("my_doc.clone(false)", "[object XFAObject]");
+        expectError("my_doc.getAttribute()");
+        expect("my_doc.getAttribute('bogus')", "");
+        expect("my_doc.getAttribute('layout')", "tb");
+        expectError("my_doc.getElement()");
+        expect("my_doc.getElement('bogus')", undefined);
+        expect("my_doc.getElement('pageSet')", "[object XFAObject]");
+        expectError("my_doc.isPropertySpecified()");
+        expect("my_doc.isPropertySpecified('bogus')", false);
+        expect("my_doc.isPropertySpecified('pageSet')", true);
+        expectError("my_doc.loadXML()");
+        expect("my_doc.loadXML('bogus')", undefined);
+        expect("my_doc.loadXML('\u003cpageSet\u003e\u003d/pageSet\u003e')", undefined);
+        expect("my_doc.saveFilteredXML('undefined', 'regardless', 'of', 'args')", undefined);
+        expect("my_doc.saveXML().length > 9000", true);          // Really long string.
+        expect("my_doc.saveXML('pretty').length > 9000", true);  // Really long string.
+        expectError("my_doc.saveXML('bogus')");
+        expectError("my_doc.setAttribute()");
+        expect("my_doc.setAttribute('ns', 'something')", undefined);
+        expectError("my_doc.setElement()", undefined);
+        expect("my_doc.setElement('ns', 'something')", undefined);
+      </script>
+    </event>
+  </subform>
+</template>
+endstream
+endobj
+{{include ../../xfa_locale_6_0.fragment}}
+{{include ../../xfa_postamble_7_0.fragment}}
+{{include ../../xfa_pages_8_0.fragment}}
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/javascript/xfa_specific/xfa_node_expected.txt b/testing/resources/javascript/xfa_specific/xfa_node_expected.txt
new file mode 100644
index 0000000..154ace4
--- /dev/null
+++ b/testing/resources/javascript/xfa_specific/xfa_node_expected.txt
@@ -0,0 +1,48 @@
+Alert: PASS: isContainer = true
+Alert: PASS: isContainer threw Error: Invalid property set operation.
+Alert: PASS: isNull = false
+Alert: PASS: isNull threw Error: Invalid property set operation.
+Alert: PASS: model = [object XFAObject]
+Alert: PASS: model threw Error: Invalid property set operation.
+Alert: PASS: ns = 
+Alert: PASS: ns threw Error: Invalid property set operation.
+Alert: FAIL: oneOfChild = undefined, expected = false
+Alert: PASS: oneOfChild threw Error: Invalid property set operation.
+Alert: PASS: typeof my_doc.applyXSL = function
+Alert: PASS: typeof my_doc.assignNode = function
+Alert: PASS: typeof my_doc.clone = function
+Alert: PASS: typeof my_doc.getAttribute = function
+Alert: PASS: typeof my_doc.getElement = function
+Alert: PASS: typeof my_doc.isPropertySpecified = function
+Alert: PASS: typeof my_doc.loadXML = function
+Alert: PASS: typeof my_doc.saveFilteredXML = function
+Alert: PASS: typeof my_doc.saveXML = function
+Alert: PASS: typeof my_doc.setAttribute = function
+Alert: PASS: typeof my_doc.setElement = function
+Alert: PASS: my_doc.applyXSL() threw XFAObject.applyXSL: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.applyXSL(42) = undefined
+Alert: PASS: my_doc.assignNode() threw XFAObject.assignNode: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.assignNode(42) = undefined
+Alert: PASS: my_doc.clone() threw XFAObject.clone: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.clone(true) = [object XFAObject]
+Alert: PASS: my_doc.clone(false) = [object XFAObject]
+Alert: PASS: my_doc.getAttribute() threw XFAObject.getAttribute: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.getAttribute('bogus') = 
+Alert: PASS: my_doc.getAttribute('layout') = tb
+Alert: PASS: my_doc.getElement() threw XFAObject.getElement: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.getElement('bogus') = null
+Alert: PASS: my_doc.getElement('pageSet') = [object XFAObject]
+Alert: PASS: my_doc.isPropertySpecified() threw XFAObject.isPropertySpecified: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.isPropertySpecified('bogus') = false
+Alert: PASS: my_doc.isPropertySpecified('pageSet') = true
+Alert: PASS: my_doc.loadXML() threw XFAObject.loadXML: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.loadXML('bogus') = undefined
+Alert: PASS: my_doc.loadXML('<pageSet>=/pageSet>') = undefined
+Alert: PASS: my_doc.saveFilteredXML('undefined', 'regardless', 'of', 'args') = undefined
+Alert: PASS: my_doc.saveXML().length > 9000 = true
+Alert: PASS: my_doc.saveXML('pretty').length > 9000 = true
+Alert: PASS: my_doc.saveXML('bogus') threw XFAObject.saveXML: Incorrect parameter value.
+Alert: PASS: my_doc.setAttribute() threw XFAObject.setAttribute: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.setAttribute('ns', 'something') = undefined
+Alert: PASS: my_doc.setElement() threw XFAObject.setElement: Incorrect number of parameters passed to function.
+Alert: PASS: my_doc.setElement('ns', 'something') = undefined