Rework XFA_ResolveNodeRS.

-- nest class as CFXJSE_Engine::ResolveResult.
-- prefer returning Optional<> over out-paramenters.
-- use inside of RNDdata.

Change-Id: I126ed580c87467197083b7cf967ff62a3d9cb8dc
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/76510
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp
index 70dab0b..1c42218 100644
--- a/fxjs/xfa/cfxjse_engine.cpp
+++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -31,7 +31,6 @@
 #include "xfa/fxfa/parser/cxfa_object.h"
 #include "xfa/fxfa/parser/cxfa_thisproxy.h"
 #include "xfa/fxfa/parser/xfa_basic_data.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
 using pdfium::fxjse::kClassTag;
@@ -75,6 +74,16 @@
 
 }  // namespace
 
+CFXJSE_Engine::ResolveResult::ResolveResult() = default;
+
+CFXJSE_Engine::ResolveResult::ResolveResult(const ResolveResult& that) =
+    default;
+
+CFXJSE_Engine::ResolveResult& CFXJSE_Engine::ResolveResult::operator=(
+    const ResolveResult& that) = default;
+
+CFXJSE_Engine::ResolveResult::~ResolveResult() = default;
+
 // static
 CXFA_Object* CFXJSE_Engine::ToObject(
     const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -177,20 +186,23 @@
   if (!refNode)
     return false;
 
-  XFA_ResolveNodeRS resolveRs;
-  if (!ResolveObjects(refNode, propname, &resolveRs, dwFlag, nullptr))
+  Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+      ResolveObjects(refNode, propname, dwFlag);
+  if (!maybeResult.has_value())
     return false;
-  if (resolveRs.dwFlags == XFA_ResolveNodeRS::Type::kNodes) {
-    pValue->ForceSetValue(GetIsolate(), GetOrCreateJSBindingFromMap(
-                                            resolveRs.objects.front().Get()));
+
+  if (maybeResult.value().type == ResolveResult::Type::kNodes) {
+    pValue->ForceSetValue(
+        GetIsolate(),
+        GetOrCreateJSBindingFromMap(maybeResult.value().objects.front().Get()));
     return true;
   }
-  if (resolveRs.dwFlags == XFA_ResolveNodeRS::Type::kAttribute &&
-      resolveRs.script_attribute.callback) {
-    CJX_Object* jsObject = resolveRs.objects.front()->JSObject();
-    (*resolveRs.script_attribute.callback)(
+  if (maybeResult.value().type == ResolveResult::Type::kAttribute &&
+      maybeResult.value().script_attribute.callback) {
+    CJX_Object* jsObject = maybeResult.value().objects.front()->JSObject();
+    (*maybeResult.value().script_attribute.callback)(
         GetIsolate(), jsObject, pValue, bSetting,
-        resolveRs.script_attribute.attribute);
+        maybeResult.value().script_attribute.attribute);
   }
   return true;
 }
@@ -621,14 +633,22 @@
   fxv8::ReentrantDeleteObjectPropertyHelper(GetIsolate(), pObject, "Date");
 }
 
-bool CFXJSE_Engine::ResolveObjects(CXFA_Object* refObject,
-                                   WideStringView wsExpression,
-                                   XFA_ResolveNodeRS* resolveNodeRS,
-                                   uint32_t dwStyles,
-                                   CXFA_Node* bindNode) {
-  if (wsExpression.IsEmpty())
-    return false;
+Optional<CFXJSE_Engine::ResolveResult> CFXJSE_Engine::ResolveObjects(
+    CXFA_Object* refObject,
+    WideStringView wsExpression,
+    uint32_t dwStyles) {
+  return ResolveObjectsWithBindNode(refObject, wsExpression, dwStyles, nullptr);
+}
 
+Optional<CFXJSE_Engine::ResolveResult>
+CFXJSE_Engine::ResolveObjectsWithBindNode(CXFA_Object* refObject,
+                                          WideStringView wsExpression,
+                                          uint32_t dwStyles,
+                                          CXFA_Node* bindNode) {
+  if (wsExpression.IsEmpty())
+    return pdfium::nullopt;
+
+  ResolveResult result;
   if (m_eScriptType != CXFA_Script::Type::Formcalc ||
       (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) {
     m_upObjectArray.clear();
@@ -705,27 +725,29 @@
       }
       rndFind.m_CurObject = findObjects[i++].Get();
       rndFind.m_nLevel = nLevel;
-      rndFind.m_dwFlag = XFA_ResolveNodeRS::Type::kNodes;
+      rndFind.m_Result.type = ResolveResult::Type::kNodes;
       if (!m_ResolveProcessor->Resolve(GetIsolate(), rndFind))
         continue;
 
-      if (rndFind.m_dwFlag == XFA_ResolveNodeRS::Type::kAttribute &&
-          rndFind.m_ScriptAttribute.callback &&
+      if (rndFind.m_Result.type == ResolveResult::Type::kAttribute &&
+          rndFind.m_Result.script_attribute.callback &&
           nStart <
               pdfium::base::checked_cast<int32_t>(wsExpression.GetLength())) {
         auto pValue = std::make_unique<CFXJSE_Value>();
-        CJX_Object* jsObject = rndFind.m_Objects.front()->JSObject();
-        (*rndFind.m_ScriptAttribute.callback)(
+        CJX_Object* jsObject = rndFind.m_Result.objects.front()->JSObject();
+        (*rndFind.m_Result.script_attribute.callback)(
             GetIsolate(), jsObject, pValue.get(), false,
-            rndFind.m_ScriptAttribute.attribute);
-        if (!pValue->IsEmpty())
-          rndFind.m_Objects.front() = ToObject(GetIsolate(), pValue.get());
+            rndFind.m_Result.script_attribute.attribute);
+        if (!pValue->IsEmpty()) {
+          rndFind.m_Result.objects.front() =
+              ToObject(GetIsolate(), pValue.get());
+        }
       }
       if (!m_upObjectArray.empty())
         m_upObjectArray.pop_back();
-      retObjects.insert(retObjects.end(), rndFind.m_Objects.begin(),
-                        rndFind.m_Objects.end());
-      rndFind.m_Objects.clear();
+      retObjects.insert(retObjects.end(), rndFind.m_Result.objects.begin(),
+                        rndFind.m_Result.objects.end());
+      rndFind.m_Result.objects.clear();
       if (bDataBind)
         break;
     }
@@ -750,7 +772,7 @@
     }
 
     findObjects = std::move(retObjects);
-    rndFind.m_Objects.clear();
+    rndFind.m_Result.objects.clear();
     if (nLevel == 0)
       dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
 
@@ -758,35 +780,41 @@
   }
 
   if (!bNextCreate) {
-    resolveNodeRS->dwFlags = rndFind.m_dwFlag;
+    result.type = rndFind.m_Result.type;
     if (nNodes > 0) {
-      resolveNodeRS->objects.insert(resolveNodeRS->objects.end(),
-                                    findObjects.begin(), findObjects.end());
+      result.objects.insert(result.objects.end(), findObjects.begin(),
+                            findObjects.end());
     }
-    if (rndFind.m_dwFlag == XFA_ResolveNodeRS::Type::kAttribute) {
-      resolveNodeRS->script_attribute = rndFind.m_ScriptAttribute;
-      return true;
+    if (rndFind.m_Result.type == ResolveResult::Type::kAttribute) {
+      result.script_attribute = rndFind.m_Result.script_attribute;
+      return result;
     }
   }
   if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind |
                   XFA_RESOLVENODE_BindNew)) {
     if (pNodeHelper->m_pCreateParent)
-      resolveNodeRS->objects.emplace_back(pNodeHelper->m_pCreateParent.Get());
+      result.objects.emplace_back(pNodeHelper->m_pCreateParent.Get());
     else
       pNodeHelper->CreateNodeForCondition(rndFind.m_wsCondition);
 
-    resolveNodeRS->dwFlags = pNodeHelper->m_iCreateFlag;
-    if (resolveNodeRS->dwFlags == XFA_ResolveNodeRS::Type::kCreateNodeOne) {
+    result.type = pNodeHelper->m_iCreateFlag;
+    if (result.type == ResolveResult::Type::kCreateNodeOne) {
       if (pNodeHelper->m_iCurAllStart != -1)
-        resolveNodeRS->dwFlags = XFA_ResolveNodeRS::Type::kCreateNodeMidAll;
+        result.type = ResolveResult::Type::kCreateNodeMidAll;
     }
 
     if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode))
-      resolveNodeRS->dwFlags = XFA_ResolveNodeRS::Type::kExistNodes;
+      result.type = ResolveResult::Type::kExistNodes;
 
-    return !resolveNodeRS->objects.empty();
+    if (result.objects.empty())
+      return pdfium::nullopt;
+
+    return result;
   }
-  return nNodes > 0;
+  if (nNodes == 0)
+    return pdfium::nullopt;
+
+  return result;
 }
 
 v8::Local<v8::Object> CFXJSE_Engine::GetOrCreateJSBindingFromMap(
diff --git a/fxjs/xfa/cfxjse_engine.h b/fxjs/xfa/cfxjse_engine.h
index 326aa9b..f6253c8 100644
--- a/fxjs/xfa/cfxjse_engine.h
+++ b/fxjs/xfa/cfxjse_engine.h
@@ -18,7 +18,7 @@
 #include "xfa/fxfa/cxfa_eventparam.h"
 #include "xfa/fxfa/parser/cxfa_document.h"
 #include "xfa/fxfa/parser/cxfa_script.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
+#include "xfa/fxfa/parser/xfa_basic_data.h"
 
 class CFXJSE_Class;
 class CFXJSE_Context;
@@ -42,6 +42,32 @@
 
 class CFXJSE_Engine final : public CFX_V8 {
  public:
+  class ResolveResult {
+    CPPGC_STACK_ALLOCATED();  // Allow raw/unowned pointers.
+
+   public:
+    enum class Type {
+      kNodes = 0,
+      kAttribute,
+      kCreateNodeOne,
+      kCreateNodeAll,
+      kCreateNodeMidAll,
+      kExistNodes,
+    };
+
+    ResolveResult();
+    ResolveResult(const ResolveResult& that);
+    ResolveResult& operator=(const ResolveResult& that);
+    ~ResolveResult();
+
+    Type type = Type::kNodes;
+    XFA_SCRIPTATTRIBUTEINFO script_attribute = {};
+
+    // Vector of Member would be correct for stack-based vectors, if
+    // STL worked with cppgc.
+    std::vector<cppgc::Member<CXFA_Object>> objects;
+  };
+
   static CXFA_Object* ToObject(const v8::FunctionCallbackInfo<v8::Value>& info);
   static CXFA_Object* ToObject(v8::Isolate* pIsolate,
                                v8::Local<v8::Value> value);
@@ -85,11 +111,15 @@
                  CFXJSE_Value* pRetValue,
                  CXFA_Object* pThisObject);
 
-  bool ResolveObjects(CXFA_Object* refObject,
-                      WideStringView wsExpression,
-                      XFA_ResolveNodeRS* resolveNodeRS,
-                      uint32_t dwStyles,
-                      CXFA_Node* bindNode);
+  Optional<ResolveResult> ResolveObjects(CXFA_Object* refObject,
+                                         WideStringView wsExpression,
+                                         uint32_t dwStyles);
+
+  Optional<ResolveResult> ResolveObjectsWithBindNode(
+      CXFA_Object* refObject,
+      WideStringView wsExpression,
+      uint32_t dwStyles,
+      CXFA_Node* bindNode);
 
   v8::Local<v8::Object> GetOrCreateJSBindingFromMap(CXFA_Object* pObject);
 
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 057de36..de914d8 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -1559,31 +1559,30 @@
     return v8::Local<v8::Value>();
 
   CFXJSE_Engine* pScriptContext = pDoc->GetScriptContext();
-  XFA_ResolveNodeRS resolveNodeRS;
   uint32_t dwFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
                      XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
-  if (!pScriptContext->ResolveObjects(
+  Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+      pScriptContext->ResolveObjects(
           pScriptContext->GetThisObject(),
-          WideString::FromUTF8(bsAccessorName).AsStringView(), &resolveNodeRS,
-          dwFlags, /*bindNode=*/nullptr)) {
+          WideString::FromUTF8(bsAccessorName).AsStringView(), dwFlags);
+  if (!maybeResult.has_value() ||
+      maybeResult.value().type != CFXJSE_Engine::ResolveResult::Type::kNodes ||
+      maybeResult.value().objects.empty()) {
     return v8::Local<v8::Value>();
   }
-  if (resolveNodeRS.dwFlags != XFA_ResolveNodeRS::Type::kNodes)
-    return v8::Local<v8::Value>();
-
   return pScriptContext->GetOrCreateJSBindingFromMap(
-      resolveNodeRS.objects.front().Get());
+      maybeResult.value().objects.front().Get());
 }
 
-bool ResolveObjects(CFXJSE_HostObject* pHostObject,
-                    v8::Local<v8::Value> pRefValue,
-                    ByteStringView bsSomExp,
-                    XFA_ResolveNodeRS* resolveNodeRS,
-                    bool bDotAccessor,
-                    bool bHasNoResolveName) {
+Optional<CFXJSE_Engine::ResolveResult> ResolveObjects(
+    CFXJSE_HostObject* pHostObject,
+    v8::Local<v8::Value> pRefValue,
+    ByteStringView bsSomExp,
+    bool bDotAccessor,
+    bool bHasNoResolveName) {
   CXFA_Document* pDoc = ToFormCalcContext(pHostObject)->GetDocument();
   if (!pDoc)
-    return false;
+    return pdfium::nullopt;
 
   v8::Isolate* pIsolate = ToFormCalcContext(pHostObject)->GetIsolate();
   WideString wsSomExpression = WideString::FromUTF8(bsSomExp);
@@ -1597,7 +1596,7 @@
     } else {
       pNode = CFXJSE_Engine::ToObject(pIsolate, pRefValue);
       if (!pNode)
-        return false;
+        return pdfium::nullopt;
 
       if (bHasNoResolveName) {
         WideString wsName;
@@ -1624,27 +1623,26 @@
     dFlags = XFA_RESOLVENODE_AnyChild;
   }
   return pScriptContext->ResolveObjects(pNode, wsSomExpression.AsStringView(),
-                                        resolveNodeRS, dFlags, nullptr);
+                                        dFlags);
 }
 
-void ParseResolveResult(CFXJSE_HostObject* pHostObject,
-                        const XFA_ResolveNodeRS& resolveNodeRS,
-                        v8::Local<v8::Value> pParentValue,
-                        std::vector<v8::Local<v8::Value>>* resultValues,
-                        bool* bAttribute) {
-  resultValues->clear();
-
+std::vector<v8::Local<v8::Value>> ParseResolveResult(
+    CFXJSE_HostObject* pHostObject,
+    const CFXJSE_Engine::ResolveResult& resolveNodeRS,
+    v8::Local<v8::Value> pParentValue,
+    bool* bAttribute) {
+  std::vector<v8::Local<v8::Value>> resultValues;
   CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pHostObject);
   v8::Isolate* pIsolate = pContext->GetIsolate();
 
-  if (resolveNodeRS.dwFlags == XFA_ResolveNodeRS::Type::kNodes) {
+  if (resolveNodeRS.type == CFXJSE_Engine::ResolveResult::Type::kNodes) {
     *bAttribute = false;
     CFXJSE_Engine* pScriptContext = pContext->GetDocument()->GetScriptContext();
     for (auto& pObject : resolveNodeRS.objects) {
-      resultValues->push_back(
+      resultValues.push_back(
           pScriptContext->GetOrCreateJSBindingFromMap(pObject.Get()));
     }
-    return;
+    return resultValues;
   }
 
   *bAttribute = true;
@@ -1656,12 +1654,14 @@
       (*resolveNodeRS.script_attribute.callback)(
           pIsolate, jsObject, pValue.get(), false,
           resolveNodeRS.script_attribute.attribute);
-      resultValues->push_back(pValue->GetValue(pIsolate));
+      resultValues.push_back(pValue->GetValue(pIsolate));
       *bAttribute = false;
     }
   }
   if (*bAttribute && fxv8::IsObject(pParentValue))
-    resultValues->push_back(pParentValue);
+    resultValues.push_back(pParentValue);
+
+  return resultValues;
 }
 
 }  // namespace
@@ -5401,12 +5401,12 @@
     for (uint32_t i = 2; i < iLength; i++) {
       v8::Local<v8::Value> hJSObjValue =
           fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, i);
-
-      XFA_ResolveNodeRS resolveNodeRS;
-      if (ResolveObjects(pThis, hJSObjValue, bsSomExp.AsStringView(),
-                         &resolveNodeRS, bDotAccessor, bHasNoResolveName)) {
-        ParseResolveResult(pThis, resolveNodeRS, hJSObjValue,
-                           &resolveValues[i - 2], &bAttribute);
+      Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+          ResolveObjects(pThis, hJSObjValue, bsSomExp.AsStringView(),
+                         bDotAccessor, bHasNoResolveName);
+      if (maybeResult.has_value()) {
+        resolveValues[i - 2] = ParseResolveResult(pThis, maybeResult.value(),
+                                                  hJSObjValue, &bAttribute);
         bAllEmpty = bAllEmpty && resolveValues[i - 2].empty();
       }
     }
@@ -5438,34 +5438,32 @@
     return;
   }
 
-  XFA_ResolveNodeRS resolveNodeRS;
-  bool bRet = false;
+  Optional<CFXJSE_Engine::ResolveResult> maybeResult;
   ByteString bsAccessorName =
       fxv8::ReentrantToByteStringHelper(info.GetIsolate(), info[1]);
   if (fxv8::IsObject(argAccessor) ||
       (fxv8::IsNull(argAccessor) && bsAccessorName.IsEmpty())) {
-    bRet = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
-                          &resolveNodeRS, bDotAccessor, bHasNoResolveName);
+    maybeResult = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
+                                 bDotAccessor, bHasNoResolveName);
   } else if (!fxv8::IsObject(argAccessor) && !bsAccessorName.IsEmpty()) {
     v8::Local<v8::Value> obj =
         GetObjectForName(pThis, bsAccessorName.AsStringView());
     if (!obj.IsEmpty()) {
       argAccessor = obj;
-      bRet = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
-                            &resolveNodeRS, bDotAccessor, bHasNoResolveName);
+      maybeResult = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
+                                   bDotAccessor, bHasNoResolveName);
     }
   }
-  if (!bRet) {
+  if (!maybeResult.has_value()) {
     pContext->ThrowPropertyNotInObjectException(
         WideString::FromUTF8(bsName.AsStringView()),
         WideString::FromUTF8(bsSomExp.AsStringView()));
     return;
   }
 
-  std::vector<v8::Local<v8::Value>> resolveValues;
   bool bAttribute = false;
-  ParseResolveResult(pThis, resolveNodeRS, argAccessor, &resolveValues,
-                     &bAttribute);
+  std::vector<v8::Local<v8::Value>> resolveValues =
+      ParseResolveResult(pThis, maybeResult.value(), argAccessor, &bAttribute);
 
   std::vector<v8::Local<v8::Value>> values(resolveValues.size() + 2);
   values[0] = fxv8::NewNumberHelper(pIsolate, 1);
diff --git a/fxjs/xfa/cfxjse_formcalc_context.h b/fxjs/xfa/cfxjse_formcalc_context.h
index ff4f367..06827d5 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.h
+++ b/fxjs/xfa/cfxjse_formcalc_context.h
@@ -15,7 +15,6 @@
 #include "core/fxcrt/unowned_ptr.h"
 #include "fxjs/xfa/fxjse.h"
 #include "third_party/base/optional.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 
 class CFXJSE_Context;
 class CFX_WideTextBuf;
diff --git a/fxjs/xfa/cfxjse_nodehelper.cpp b/fxjs/xfa/cfxjse_nodehelper.cpp
index f6b6932..508a1c1 100644
--- a/fxjs/xfa/cfxjse_nodehelper.cpp
+++ b/fxjs/xfa/cfxjse_nodehelper.cpp
@@ -13,7 +13,6 @@
 #include "xfa/fxfa/parser/cxfa_localemgr.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/xfa_basic_data.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
 CFXJSE_NodeHelper::CFXJSE_NodeHelper() = default;
@@ -25,7 +24,7 @@
   WideString wsIndex(L"0");
   bool bAll = false;
   if (szLen == 0) {
-    m_iCreateFlag = XFA_ResolveNodeRS::Type::kCreateNodeOne;
+    m_iCreateFlag = CFXJSE_Engine::ResolveResult::Type::kCreateNodeOne;
     return false;
   }
   if (wsCondition[0] != '[')
@@ -43,9 +42,9 @@
   }
   if (bAll) {
     wsIndex = L"1";
-    m_iCreateFlag = XFA_ResolveNodeRS::Type::kCreateNodeAll;
+    m_iCreateFlag = CFXJSE_Engine::ResolveResult::Type::kCreateNodeAll;
   } else {
-    m_iCreateFlag = XFA_ResolveNodeRS::Type::kCreateNodeOne;
+    m_iCreateFlag = CFXJSE_Engine::ResolveResult::Type::kCreateNodeOne;
     wsIndex = wsCondition.Substr(i, szLen - 1 - i);
   }
   int32_t iCount = wsIndex.GetInteger();
diff --git a/fxjs/xfa/cfxjse_nodehelper.h b/fxjs/xfa/cfxjse_nodehelper.h
index 39ea232..01e27f4 100644
--- a/fxjs/xfa/cfxjse_nodehelper.h
+++ b/fxjs/xfa/cfxjse_nodehelper.h
@@ -8,11 +8,10 @@
 #define FXJS_XFA_CFXJSE_NODEHELPER_H_
 
 #include "core/fxcrt/fx_string.h"
+#include "fxjs/xfa/cfxjse_engine.h"
 #include "v8/include/cppgc/persistent.h"
 #include "xfa/fxfa/fxfa_basic.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 
-class CFXJSE_Engine;
 class CXFA_Node;
 
 class CFXJSE_NodeHelper {
@@ -28,8 +27,8 @@
   void SetCreateNodeType(CXFA_Node* refNode);
 
   XFA_Element m_eLastCreateType = XFA_Element::DataValue;
-  XFA_ResolveNodeRS::Type m_iCreateFlag =
-      XFA_ResolveNodeRS::Type::kCreateNodeOne;
+  CFXJSE_Engine::ResolveResult::Type m_iCreateFlag =
+      CFXJSE_Engine::ResolveResult::Type::kCreateNodeOne;
   size_t m_iCreateCount = 0;
   int32_t m_iCurAllStart = -1;
   cppgc::Persistent<CXFA_Node> m_pCreateParent;
diff --git a/fxjs/xfa/cfxjse_resolveprocessor.cpp b/fxjs/xfa/cfxjse_resolveprocessor.cpp
index a187f1d..e9dc7a7 100644
--- a/fxjs/xfa/cfxjse_resolveprocessor.cpp
+++ b/fxjs/xfa/cfxjse_resolveprocessor.cpp
@@ -21,7 +21,6 @@
 #include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/cxfa_object.h"
 #include "xfa/fxfa/parser/cxfa_occur.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
 namespace {
@@ -30,7 +29,7 @@
                        WideString wsCondition,
                        size_t iFoundCount,
                        CFXJSE_ResolveNodeData* pRnd) {
-  ASSERT(iFoundCount == pRnd->m_Objects.size());
+  ASSERT(iFoundCount == pRnd->m_Result.objects.size());
   WideString wsExpression;
   CXFA_Script::Type eLangType = CXFA_Script::Type::Unknown;
   if (wsCondition.First(2).EqualsASCII(".[") && wsCondition.Back() == L']')
@@ -43,11 +42,11 @@
   wsExpression = wsCondition.Substr(2, wsCondition.GetLength() - 3);
   for (size_t i = iFoundCount; i > 0; --i) {
     auto pRetValue = std::make_unique<CFXJSE_Value>();
-    bool bRet =
-        pRnd->m_pSC->RunScript(eLangType, wsExpression.AsStringView(),
-                               pRetValue.get(), pRnd->m_Objects[i - 1].Get());
+    bool bRet = pRnd->m_pSC->RunScript(eLangType, wsExpression.AsStringView(),
+                                       pRetValue.get(),
+                                       pRnd->m_Result.objects[i - 1].Get());
     if (!bRet || !pRetValue->ToBoolean(pIsolate))
-      pRnd->m_Objects.erase(pRnd->m_Objects.begin() + i - 1);
+      pRnd->m_Result.objects.erase(pRnd->m_Result.objects.begin() + i - 1);
   }
 }
 
@@ -65,7 +64,7 @@
 
   if (!rnd.m_CurObject->IsNode()) {
     if (rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) {
-      return ResolveForAttributeRs(rnd.m_CurObject.Get(), rnd,
+      return ResolveForAttributeRs(rnd.m_CurObject.Get(), &rnd.m_Result,
                                    rnd.m_wsName.AsStringView());
     }
     return false;
@@ -92,30 +91,30 @@
     }
   }
   if (rnd.m_uHashName == XFA_HASHCODE_This && rnd.m_nLevel == 0) {
-    rnd.m_Objects.emplace_back(rnd.m_pSC->GetThisObject());
+    rnd.m_Result.objects.emplace_back(rnd.m_pSC->GetThisObject());
     return true;
   }
   if (rnd.m_CurObject->GetElementType() == XFA_Element::Xfa) {
     CXFA_Object* pObjNode =
         rnd.m_pSC->GetDocument()->GetXFAObject(rnd.m_uHashName);
     if (pObjNode) {
-      rnd.m_Objects.emplace_back(pObjNode);
+      rnd.m_Result.objects.emplace_back(pObjNode);
     } else if (rnd.m_uHashName == XFA_HASHCODE_Xfa) {
-      rnd.m_Objects.emplace_back(rnd.m_CurObject.Get());
+      rnd.m_Result.objects.emplace_back(rnd.m_CurObject.Get());
     } else if ((rnd.m_dwStyles & XFA_RESOLVENODE_Attributes) &&
-               ResolveForAttributeRs(rnd.m_CurObject.Get(), rnd,
+               ResolveForAttributeRs(rnd.m_CurObject.Get(), &rnd.m_Result,
                                      rnd.m_wsName.AsStringView())) {
       return true;
     }
-    if (!rnd.m_Objects.empty())
+    if (!rnd.m_Result.objects.empty())
       FilterCondition(pIsolate, rnd.m_wsCondition, &rnd);
 
-    return !rnd.m_Objects.empty();
+    return !rnd.m_Result.objects.empty();
   }
   if (!ResolveNormal(pIsolate, rnd) && rnd.m_uHashName == XFA_HASHCODE_Xfa)
-    rnd.m_Objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
+    rnd.m_Result.objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
 
-  return !rnd.m_Objects.empty();
+  return !rnd.m_Result.objects.empty();
 }
 
 bool CFXJSE_ResolveProcessor::ResolveAnyChild(v8::Isolate* pIsolate,
@@ -135,20 +134,20 @@
     return false;
 
   if (wsCondition.IsEmpty()) {
-    rnd.m_Objects.emplace_back(pChild);
+    rnd.m_Result.objects.emplace_back(pChild);
     return true;
   }
 
   std::vector<CXFA_Node*> nodes;
-  for (const auto& pObject : rnd.m_Objects)
+  for (const auto& pObject : rnd.m_Result.objects)
     nodes.push_back(pObject->AsNode());
 
   std::vector<CXFA_Node*> siblings = pChild->GetSiblings(bClassName);
   nodes.insert(nodes.end(), siblings.begin(), siblings.end());
-  rnd.m_Objects =
-      std::vector<UnownedPtr<CXFA_Object>>(nodes.begin(), nodes.end());
+  rnd.m_Result.objects =
+      std::vector<cppgc::Member<CXFA_Object>>(nodes.begin(), nodes.end());
   FilterCondition(pIsolate, wsCondition, &rnd);
-  return !rnd.m_Objects.empty();
+  return !rnd.m_Result.objects.empty();
 }
 
 bool CFXJSE_ResolveProcessor::ResolveDollar(v8::Isolate* pIsolate,
@@ -157,7 +156,7 @@
   WideString wsCondition = rnd.m_wsCondition;
   int32_t iNameLen = wsName.GetLength();
   if (iNameLen == 1) {
-    rnd.m_Objects.emplace_back(rnd.m_CurObject.Get());
+    rnd.m_Result.objects.emplace_back(rnd.m_CurObject.Get());
     return true;
   }
   if (rnd.m_nLevel > 0)
@@ -166,15 +165,15 @@
   XFA_HashCode dwNameHash = static_cast<XFA_HashCode>(
       FX_HashCode_GetW(wsName.AsStringView().Last(iNameLen - 1), false));
   if (dwNameHash == XFA_HASHCODE_Xfa) {
-    rnd.m_Objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
+    rnd.m_Result.objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
   } else {
     CXFA_Object* pObjNode = rnd.m_pSC->GetDocument()->GetXFAObject(dwNameHash);
     if (pObjNode)
-      rnd.m_Objects.emplace_back(pObjNode);
+      rnd.m_Result.objects.emplace_back(pObjNode);
   }
-  if (!rnd.m_Objects.empty())
+  if (!rnd.m_Result.objects.empty())
     FilterCondition(pIsolate, wsCondition, &rnd);
-  return !rnd.m_Objects.empty();
+  return !rnd.m_Result.objects.empty();
 }
 
 bool CFXJSE_ResolveProcessor::ResolveExcalmatory(v8::Isolate* pIsolate,
@@ -197,9 +196,10 @@
   rndFind.m_wsCondition = rnd.m_wsCondition;
   Resolve(pIsolate, rndFind);
 
-  rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
-                       rndFind.m_Objects.end());
-  return !rnd.m_Objects.empty();
+  rnd.m_Result.objects.insert(rnd.m_Result.objects.end(),
+                              rndFind.m_Result.objects.begin(),
+                              rndFind.m_Result.objects.end());
+  return !rnd.m_Result.objects.empty();
 }
 
 bool CFXJSE_ResolveProcessor::ResolveNumberSign(v8::Isolate* pIsolate,
@@ -207,7 +207,7 @@
   WideString wsName = rnd.m_wsName.Last(rnd.m_wsName.GetLength() - 1);
   WideString wsCondition = rnd.m_wsCondition;
   CXFA_Node* curNode = ToNode(rnd.m_CurObject.Get());
-  if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView()))
+  if (ResolveForAttributeRs(curNode, &rnd.m_Result, wsName.AsStringView()))
     return true;
 
   CFXJSE_ResolveNodeData rndFind(rnd.m_pSC.Get());
@@ -221,29 +221,32 @@
   rndFind.m_wsCondition = wsCondition;
   rndFind.m_CurObject = curNode;
   ResolveNormal(pIsolate, rndFind);
-  if (rndFind.m_Objects.empty())
+  if (rndFind.m_Result.objects.empty())
     return false;
 
-  if (wsCondition.IsEmpty() && pdfium::Contains(rndFind.m_Objects, curNode)) {
-    rnd.m_Objects.emplace_back(curNode);
+  if (wsCondition.IsEmpty() &&
+      pdfium::Contains(rndFind.m_Result.objects, curNode)) {
+    rnd.m_Result.objects.emplace_back(curNode);
   } else {
-    rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
-                         rndFind.m_Objects.end());
+    rnd.m_Result.objects.insert(rnd.m_Result.objects.end(),
+                                rndFind.m_Result.objects.begin(),
+                                rndFind.m_Result.objects.end());
   }
-  return !rnd.m_Objects.empty();
+  return !rnd.m_Result.objects.empty();
 }
 
-bool CFXJSE_ResolveProcessor::ResolveForAttributeRs(CXFA_Object* curNode,
-                                                    CFXJSE_ResolveNodeData& rnd,
-                                                    WideStringView strAttr) {
+bool CFXJSE_ResolveProcessor::ResolveForAttributeRs(
+    CXFA_Object* curNode,
+    CFXJSE_Engine::ResolveResult* rnd,
+    WideStringView strAttr) {
   Optional<XFA_SCRIPTATTRIBUTEINFO> info =
       XFA_GetScriptAttributeByName(curNode->GetElementType(), strAttr);
   if (!info.has_value())
     return false;
 
-  rnd.m_ScriptAttribute = info.value();
-  rnd.m_Objects.emplace_back(curNode);
-  rnd.m_dwFlag = XFA_ResolveNodeRS::Type::kAttribute;
+  rnd->type = CFXJSE_Engine::ResolveResult::Type::kAttribute;
+  rnd->script_attribute = info.value();
+  rnd->objects.emplace_back(curNode);
   return true;
 }
 
@@ -253,7 +256,7 @@
     return false;
 
   CXFA_Node* curNode = rnd.m_CurObject->AsNode();
-  size_t nNum = rnd.m_Objects.size();
+  size_t nNum = rnd.m_Result.objects.size();
   uint32_t dwStyles = rnd.m_dwStyles;
   WideString& wsName = rnd.m_wsName;
   XFA_HashCode uNameHash = rnd.m_uHashName;
@@ -286,20 +289,21 @@
   }
   if ((dwStyles & XFA_RESOLVENODE_Properties) && pVariablesNode) {
     if (pVariablesNode->GetClassHashCode() == uNameHash) {
-      rnd.m_Objects.emplace_back(pVariablesNode);
+      rnd.m_Result.objects.emplace_back(pVariablesNode);
     } else {
       rndFind.m_CurObject = pVariablesNode;
       SetStylesForChild(dwStyles, rndFind);
       WideString wsSaveCondition = std::move(rndFind.m_wsCondition);
       ResolveNormal(pIsolate, rndFind);
       rndFind.m_wsCondition = std::move(wsSaveCondition);
-      rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
-                           rndFind.m_Objects.end());
-      rndFind.m_Objects.clear();
+      rnd.m_Result.objects.insert(rnd.m_Result.objects.end(),
+                                  rndFind.m_Result.objects.begin(),
+                                  rndFind.m_Result.objects.end());
+      rndFind.m_Result.objects.clear();
     }
-    if (rnd.m_Objects.size() > nNum) {
+    if (rnd.m_Result.objects.size() > nNum) {
       FilterCondition(pIsolate, wsCondition, &rnd);
-      return !rnd.m_Objects.empty();
+      return !rnd.m_Result.objects.empty();
     }
   }
 
@@ -311,9 +315,9 @@
     for (CXFA_Node* child : children) {
       if (dwStyles & XFA_RESOLVENODE_TagName) {
         if (child->GetClassHashCode() == uNameHash)
-          rnd.m_Objects.emplace_back(child);
+          rnd.m_Result.objects.emplace_back(child);
       } else if (child->GetNameHash() == uNameHash) {
-        rnd.m_Objects.emplace_back(child);
+        rnd.m_Result.objects.emplace_back(child);
       }
 
       if (child->GetElementType() != XFA_Element::PageSet &&
@@ -327,52 +331,53 @@
         WideString wsSaveCondition = std::move(rndFind.m_wsCondition);
         ResolveNormal(pIsolate, rndFind);
         rndFind.m_wsCondition = std::move(wsSaveCondition);
-        rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
-                             rndFind.m_Objects.end());
-        rndFind.m_Objects.clear();
+        rnd.m_Result.objects.insert(rnd.m_Result.objects.end(),
+                                    rndFind.m_Result.objects.begin(),
+                                    rndFind.m_Result.objects.end());
+        rndFind.m_Result.objects.clear();
       }
     }
-    if (rnd.m_Objects.size() > nNum) {
+    if (rnd.m_Result.objects.size() > nNum) {
       if (!(dwStyles & XFA_RESOLVENODE_ALL)) {
         std::vector<CXFA_Node*> upArrayNodes;
         if (curNode->IsTransparent()) {
-          CXFA_Node* pCurrent = ToNode(rnd.m_Objects.front().Get());
+          CXFA_Node* pCurrent = ToNode(rnd.m_Result.objects.front().Get());
           if (pCurrent) {
             upArrayNodes =
                 pCurrent->GetSiblings(!!(dwStyles & XFA_RESOLVENODE_TagName));
           }
         }
-        if (upArrayNodes.size() > rnd.m_Objects.size()) {
-          CXFA_Object* pSaveObject = rnd.m_Objects.front().Get();
-          rnd.m_Objects = std::vector<UnownedPtr<CXFA_Object>>(
+        if (upArrayNodes.size() > rnd.m_Result.objects.size()) {
+          CXFA_Object* pSaveObject = rnd.m_Result.objects.front().Get();
+          rnd.m_Result.objects = std::vector<cppgc::Member<CXFA_Object>>(
               upArrayNodes.begin(), upArrayNodes.end());
-          rnd.m_Objects.front() = pSaveObject;
+          rnd.m_Result.objects.front() = pSaveObject;
         }
       }
       FilterCondition(pIsolate, wsCondition, &rnd);
-      return !rnd.m_Objects.empty();
+      return !rnd.m_Result.objects.empty();
     }
   }
   if (dwStyles & XFA_RESOLVENODE_Attributes) {
-    if (ResolveForAttributeRs(curNode, rnd, wsName.AsStringView()))
+    if (ResolveForAttributeRs(curNode, &rnd.m_Result, wsName.AsStringView()))
       return 1;
   }
   if (dwStyles & XFA_RESOLVENODE_Properties) {
     for (CXFA_Node* pChildProperty : properties) {
       if (pChildProperty->IsUnnamed()) {
         if (pChildProperty->GetClassHashCode() == uNameHash)
-          rnd.m_Objects.emplace_back(pChildProperty);
+          rnd.m_Result.objects.emplace_back(pChildProperty);
         continue;
       }
       if (pChildProperty->GetNameHash() == uNameHash &&
           pChildProperty->GetElementType() != XFA_Element::Extras &&
           pChildProperty->GetElementType() != XFA_Element::Items) {
-        rnd.m_Objects.emplace_back(pChildProperty);
+        rnd.m_Result.objects.emplace_back(pChildProperty);
       }
     }
-    if (rnd.m_Objects.size() > nNum) {
+    if (rnd.m_Result.objects.size() > nNum) {
       FilterCondition(pIsolate, wsCondition, &rnd);
-      return !rnd.m_Objects.empty();
+      return !rnd.m_Result.objects.empty();
     }
 
     CXFA_Node* pProp = nullptr;
@@ -392,8 +397,8 @@
       }
     }
     if (pProp) {
-      rnd.m_Objects.emplace_back(pProp);
-      return !rnd.m_Objects.empty();
+      rnd.m_Result.objects.emplace_back(pProp);
+      return !rnd.m_Result.objects.empty();
     }
   }
 
@@ -401,9 +406,9 @@
   uint32_t uCurClassHash = curNode->GetClassHashCode();
   if (!parentNode) {
     if (uCurClassHash == uNameHash) {
-      rnd.m_Objects.emplace_back(curNode);
+      rnd.m_Result.objects.emplace_back(curNode);
       FilterCondition(pIsolate, wsCondition, &rnd);
-      if (!rnd.m_Objects.empty())
+      if (!rnd.m_Result.objects.empty())
         return true;
     }
     return false;
@@ -423,13 +428,13 @@
       if (child == curNode) {
         if (dwStyles & XFA_RESOLVENODE_TagName) {
           if (uCurClassHash == uNameHash)
-            rnd.m_Objects.emplace_back(curNode);
+            rnd.m_Result.objects.emplace_back(curNode);
         } else {
           if (child->GetNameHash() == uNameHash) {
-            rnd.m_Objects.emplace_back(curNode);
+            rnd.m_Result.objects.emplace_back(curNode);
             if (rnd.m_nLevel == 0 && wsCondition.IsEmpty()) {
-              rnd.m_Objects.clear();
-              rnd.m_Objects.emplace_back(curNode);
+              rnd.m_Result.objects.clear();
+              rnd.m_Result.objects.emplace_back(curNode);
               return true;
             }
           }
@@ -440,9 +445,9 @@
 
       if (dwStyles & XFA_RESOLVENODE_TagName) {
         if (child->GetClassHashCode() == uNameHash)
-          rnd.m_Objects.emplace_back(child);
+          rnd.m_Result.objects.emplace_back(child);
       } else if (child->GetNameHash() == uNameHash) {
-        rnd.m_Objects.emplace_back(child);
+        rnd.m_Result.objects.emplace_back(child);
       }
 
       bool bInnerSearch = false;
@@ -462,29 +467,30 @@
         ResolveNormal(pIsolate, rndFind);
         rndFind.m_dwStyles = dwOriginStyle;
         rndFind.m_wsCondition = std::move(wsOriginCondition);
-        rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
-                             rndFind.m_Objects.end());
-        rndFind.m_Objects.clear();
+        rnd.m_Result.objects.insert(rnd.m_Result.objects.end(),
+                                    rndFind.m_Result.objects.begin(),
+                                    rndFind.m_Result.objects.end());
+        rndFind.m_Result.objects.clear();
       }
       child = child->GetNextSibling();
     }
-    if (rnd.m_Objects.size() > nNum) {
+    if (rnd.m_Result.objects.size() > nNum) {
       if (parentNode->IsTransparent()) {
         std::vector<CXFA_Node*> upArrayNodes;
-        CXFA_Node* pCurrent = ToNode(rnd.m_Objects.front().Get());
+        CXFA_Node* pCurrent = ToNode(rnd.m_Result.objects.front().Get());
         if (pCurrent) {
           upArrayNodes =
               pCurrent->GetSiblings(!!(dwStyles & XFA_RESOLVENODE_TagName));
         }
-        if (upArrayNodes.size() > rnd.m_Objects.size()) {
-          CXFA_Object* pSaveObject = rnd.m_Objects.front().Get();
-          rnd.m_Objects = std::vector<UnownedPtr<CXFA_Object>>(
+        if (upArrayNodes.size() > rnd.m_Result.objects.size()) {
+          CXFA_Object* pSaveObject = rnd.m_Result.objects.front().Get();
+          rnd.m_Result.objects = std::vector<cppgc::Member<CXFA_Object>>(
               upArrayNodes.begin(), upArrayNodes.end());
-          rnd.m_Objects.front() = pSaveObject;
+          rnd.m_Result.objects.front() = pSaveObject;
         }
       }
       FilterCondition(pIsolate, wsCondition, &rnd);
-      return !rnd.m_Objects.empty();
+      return !rnd.m_Result.objects.empty();
     }
   }
 
@@ -500,10 +506,11 @@
     rndFind.m_CurObject = parentNode;
     rnd.m_pSC->GetUpObjectArray()->push_back(parentNode);
     ResolveNormal(pIsolate, rndFind);
-    rnd.m_Objects.insert(rnd.m_Objects.end(), rndFind.m_Objects.begin(),
-                         rndFind.m_Objects.end());
-    rndFind.m_Objects.clear();
-    if (rnd.m_Objects.size() > nNum)
+    rnd.m_Result.objects.insert(rnd.m_Result.objects.end(),
+                                rndFind.m_Result.objects.begin(),
+                                rndFind.m_Result.objects.end());
+    rndFind.m_Result.objects.clear();
+    if (rnd.m_Result.objects.size() > nNum)
       return true;
   }
   return false;
@@ -513,8 +520,9 @@
   CXFA_Node* curNode = ToNode(rnd.m_CurObject.Get());
   std::vector<CXFA_Node*> array = curNode->GetNodeListWithFilter(
       XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties);
-  rnd.m_Objects.insert(rnd.m_Objects.end(), array.begin(), array.end());
-  return !rnd.m_Objects.empty();
+  rnd.m_Result.objects.insert(rnd.m_Result.objects.end(), array.begin(),
+                              array.end());
+  return !rnd.m_Result.objects.empty();
 }
 
 int32_t CFXJSE_ResolveProcessor::GetFilter(WideStringView wsExpression,
@@ -621,7 +629,7 @@
       if (pRnd->m_dwStyles & XFA_RESOLVENODE_Bind) {
         m_pNodeHelper->m_pCreateParent = ToNode(pRnd->m_CurObject.Get());
         m_pNodeHelper->m_iCreateCount = 1;
-        pRnd->m_Objects.clear();
+        pRnd->m_Result.objects.clear();
         m_pNodeHelper->m_iCurAllStart = -1;
         m_pNodeHelper->m_pAllStartParent = nullptr;
       } else if (m_pNodeHelper->m_iCurAllStart == -1) {
@@ -646,10 +654,10 @@
       m_pNodeHelper->m_pCreateParent = ToNode(pRnd->m_CurObject.Get());
       m_pNodeHelper->m_iCreateCount = iIndex - iFoundCount + 1;
     }
-    pRnd->m_Objects.clear();
+    pRnd->m_Result.objects.clear();
   } else {
-    pRnd->m_Objects =
-        std::vector<UnownedPtr<CXFA_Object>>(1, pRnd->m_Objects[iIndex]);
+    pRnd->m_Result.objects = std::vector<cppgc::Member<CXFA_Object>>(
+        1, pRnd->m_Result.objects[iIndex]);
   }
 }
 
@@ -667,7 +675,7 @@
     iCurIndex = pNode->GetIndex(bIsProperty, bIsClassIndex);
   }
 
-  size_t iFoundCount = pRnd->m_Objects.size();
+  size_t iFoundCount = pRnd->m_Result.objects.size();
   wsCondition.Trim();
 
   int32_t iLen = wsCondition.GetLength();
@@ -682,12 +690,12 @@
         m_pNodeHelper->m_pCreateParent = ToNode(pRnd->m_CurObject.Get());
         m_pNodeHelper->m_iCreateCount = iCurIndex - iFoundCount + 1;
       }
-      pRnd->m_Objects.clear();
+      pRnd->m_Result.objects.clear();
       return;
     }
 
-    pRnd->m_Objects =
-        std::vector<UnownedPtr<CXFA_Object>>(1, pRnd->m_Objects[iCurIndex]);
+    pRnd->m_Result.objects = std::vector<cppgc::Member<CXFA_Object>>(
+        1, pRnd->m_Result.objects[iCurIndex]);
     return;
   }
 
diff --git a/fxjs/xfa/cfxjse_resolveprocessor.h b/fxjs/xfa/cfxjse_resolveprocessor.h
index 139b79a..9e32a1f 100644
--- a/fxjs/xfa/cfxjse_resolveprocessor.h
+++ b/fxjs/xfa/cfxjse_resolveprocessor.h
@@ -16,7 +16,6 @@
 #include "v8/include/cppgc/macros.h"
 #include "xfa/fxfa/fxfa_basic.h"
 #include "xfa/fxfa/parser/xfa_basic_data.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 
 class CFXJSE_NodeHelper;
 
@@ -34,9 +33,7 @@
   XFA_HashCode m_uHashName = XFA_HASHCODE_None;
   int32_t m_nLevel = 0;
   uint32_t m_dwStyles = XFA_RESOLVENODE_Children;
-  XFA_ResolveNodeRS::Type m_dwFlag = XFA_ResolveNodeRS::Type::kNodes;
-  std::vector<UnownedPtr<CXFA_Object>> m_Objects;  // Ok, stack-only.
-  XFA_SCRIPTATTRIBUTEINFO m_ScriptAttribute;
+  CFXJSE_Engine::ResolveResult m_Result;
 };
 
 class CFXJSE_ResolveProcessor {
@@ -57,7 +54,7 @@
 
  private:
   bool ResolveForAttributeRs(CXFA_Object* curNode,
-                             CFXJSE_ResolveNodeData& rnd,
+                             CFXJSE_Engine::ResolveResult* rnd,
                              WideStringView strAttr);
   bool ResolveAnyChild(v8::Isolate* pIsolate, CFXJSE_ResolveNodeData& rnd);
   bool ResolveDollar(v8::Isolate* pIsolate, CFXJSE_ResolveNodeData& rnd);
diff --git a/fxjs/xfa/cjx_hostpseudomodel.cpp b/fxjs/xfa/cjx_hostpseudomodel.cpp
index b06fd06..bb52e67 100644
--- a/fxjs/xfa/cjx_hostpseudomodel.cpp
+++ b/fxjs/xfa/cjx_hostpseudomodel.cpp
@@ -16,7 +16,6 @@
 #include "xfa/fxfa/cxfa_ffnotify.h"
 #include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 
 namespace {
 
@@ -296,16 +295,15 @@
 
     uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent |
                       XFA_RESOLVENODE_Siblings;
-    XFA_ResolveNodeRS resolveNodeRS;
-    bool bRet = pScriptContext->ResolveObjects(
-        pObject, runtime->ToWideString(params[0]).AsStringView(),
-        &resolveNodeRS, dwFlag, nullptr);
-    if (!bRet || !resolveNodeRS.objects.front()->IsNode())
+    Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+        pScriptContext->ResolveObjects(
+            pObject, runtime->ToWideString(params[0]).AsStringView(), dwFlag);
+    if (!maybeResult.has_value() ||
+        !maybeResult.value().objects.front()->IsNode()) {
       return CJS_Result::Success();
-
-    pNode = resolveNodeRS.objects.front()->AsNode();
+    }
+    pNode = maybeResult.value().objects.front()->AsNode();
   }
-
   if (pNode)
     pNotify->OpenDropDownList(pNode);
 
@@ -382,13 +380,13 @@
 
     uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent |
                       XFA_RESOLVENODE_Siblings;
-    XFA_ResolveNodeRS resolveNodeRS;
-    bool bRet = pScriptContext->ResolveObjects(pObject, wsName.AsStringView(),
-                                               &resolveNodeRS, dwFlag, nullptr);
-    if (!bRet || !resolveNodeRS.objects.front()->IsNode())
+    Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+        pScriptContext->ResolveObjects(pObject, wsName.AsStringView(), dwFlag);
+    if (!maybeResult.has_value() ||
+        !maybeResult.value().objects.front()->IsNode())
       continue;
 
-    pNode = resolveNodeRS.objects.front()->AsNode();
+    pNode = maybeResult.value().objects.front()->AsNode();
     pNotify->ResetData(pNode->IsWidgetReady() ? pNode : nullptr);
   }
   if (!pNode)
@@ -444,14 +442,14 @@
 
       uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Parent |
                         XFA_RESOLVENODE_Siblings;
-      XFA_ResolveNodeRS resolveNodeRS;
-      bool bRet = pScriptContext->ResolveObjects(
-          pObject, runtime->ToWideString(params[0]).AsStringView(),
-          &resolveNodeRS, dwFlag, nullptr);
-      if (!bRet || !resolveNodeRS.objects.front()->IsNode())
+      Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+          pScriptContext->ResolveObjects(
+              pObject, runtime->ToWideString(params[0]).AsStringView(), dwFlag);
+      if (!maybeResult.has_value() ||
+          !maybeResult.value().objects.front()->IsNode()) {
         return CJS_Result::Success();
-
-      pNode = resolveNodeRS.objects.front()->AsNode();
+      }
+      pNode = maybeResult.value().objects.front()->AsNode();
     }
   }
   pNotify->SetFocusWidgetNode(pNode);
diff --git a/fxjs/xfa/cjx_object.cpp b/fxjs/xfa/cjx_object.cpp
index f1defde..7426c19 100644
--- a/fxjs/xfa/cjx_object.cpp
+++ b/fxjs/xfa/cjx_object.cpp
@@ -979,16 +979,17 @@
 
   CXFA_Node* pProtoNode = nullptr;
   if (!wsSOM.IsEmpty()) {
-    XFA_ResolveNodeRS resolveNodeRS;
-    bool bRet = GetDocument()->GetScriptContext()->ResolveObjects(
-        pProtoRoot, wsSOM.AsStringView(), &resolveNodeRS,
+    constexpr uint32_t dwFlag =
         XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
-            XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
-            XFA_RESOLVENODE_Siblings,
-        nullptr);
-    if (bRet && resolveNodeRS.objects.front()->IsNode())
-      pProtoNode = resolveNodeRS.objects.front()->AsNode();
-
+        XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
+        XFA_RESOLVENODE_Siblings;
+    Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+        GetDocument()->GetScriptContext()->ResolveObjects(
+            pProtoRoot, wsSOM.AsStringView(), dwFlag);
+    if (maybeResult.has_value() &&
+        maybeResult.value().objects.front()->IsNode()) {
+      pProtoNode = maybeResult.value().objects.front()->AsNode();
+    }
   } else if (!wsID.IsEmpty()) {
     pProtoNode = GetDocument()->GetNodeByID(pProtoRoot, wsID.AsStringView());
   }
diff --git a/fxjs/xfa/cjx_tree.cpp b/fxjs/xfa/cjx_tree.cpp
index a074ad1..ae49ea2 100644
--- a/fxjs/xfa/cjx_tree.cpp
+++ b/fxjs/xfa/cjx_tree.cpp
@@ -19,7 +19,6 @@
 #include "xfa/fxfa/parser/cxfa_document.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/cxfa_object.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 
 const CJX_MethodSpec CJX_Tree::MethodSpecs[] = {
     {"resolveNode", resolveNode_static},
@@ -50,30 +49,29 @@
   uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
                     XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
                     XFA_RESOLVENODE_Siblings;
-  XFA_ResolveNodeRS resolveNodeRS;
-  if (!pScriptContext->ResolveObjects(ToNode(refNode),
-                                      expression.AsStringView(), &resolveNodeRS,
-                                      dwFlag, nullptr)) {
+  Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+      pScriptContext->ResolveObjects(ToNode(refNode), expression.AsStringView(),
+                                     dwFlag);
+  if (!maybeResult.has_value())
     return CJS_Result::Success(runtime->NewNull());
-  }
 
-  if (resolveNodeRS.dwFlags == XFA_ResolveNodeRS::Type::kNodes) {
-    CXFA_Object* pObject = resolveNodeRS.objects.front().Get();
+  if (maybeResult.value().type == CFXJSE_Engine::ResolveResult::Type::kNodes) {
     return CJS_Result::Success(
         GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
-            pObject));
+            maybeResult.value().objects.front().Get()));
   }
 
-  if (!resolveNodeRS.script_attribute.callback ||
-      resolveNodeRS.script_attribute.eValueType != XFA_ScriptType::Object) {
+  if (!maybeResult.value().script_attribute.callback ||
+      maybeResult.value().script_attribute.eValueType !=
+          XFA_ScriptType::Object) {
     return CJS_Result::Success(runtime->NewNull());
   }
 
   auto pValue = std::make_unique<CFXJSE_Value>();
-  CJX_Object* jsObject = resolveNodeRS.objects.front()->JSObject();
-  (*resolveNodeRS.script_attribute.callback)(
+  CJX_Object* jsObject = maybeResult.value().objects.front()->JSObject();
+  (*maybeResult.value().script_attribute.callback)(
       runtime->GetIsolate(), jsObject, pValue.get(), false,
-      resolveNodeRS.script_attribute.attribute);
+      maybeResult.value().script_attribute.attribute);
   return CJS_Result::Success(
       pValue->DirectGetValue().Get(runtime->GetIsolate()));
 }
@@ -218,34 +216,38 @@
   if (!refNode)
     refNode = GetXFANode();
 
-  XFA_ResolveNodeRS resolveNodeRS;
   CXFA_Document* pDoc = GetDocument();
   CFXJSE_Engine* pScriptContext = pDoc->GetScriptContext();
-  pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(),
-                                 &resolveNodeRS, dwFlag, nullptr);
+  Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+      pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(),
+                                     dwFlag);
 
   auto* pNodeList = cppgc::MakeGarbageCollected<CXFA_ArrayNodeList>(
       pDoc->GetHeap()->GetAllocationHandle(), pDoc);
   pDoc->GetNodeOwner()->PersistList(pNodeList);
 
-  if (resolveNodeRS.dwFlags == XFA_ResolveNodeRS::Type::kNodes) {
-    for (auto& pObject : resolveNodeRS.objects) {
-      if (pObject->IsNode())
-        pNodeList->Append(pObject->AsNode());
-    }
-  } else {
-    if (resolveNodeRS.script_attribute.callback &&
-        resolveNodeRS.script_attribute.eValueType == XFA_ScriptType::Object) {
-      for (auto& pObject : resolveNodeRS.objects) {
-        auto innerValue = std::make_unique<CFXJSE_Value>();
-        CJX_Object* jsObject = pObject->JSObject();
-        (*resolveNodeRS.script_attribute.callback)(
-            pIsolate, jsObject, innerValue.get(), false,
-            resolveNodeRS.script_attribute.attribute);
-        CXFA_Object* obj = CFXJSE_Engine::ToObject(pScriptContext->GetIsolate(),
-                                                   innerValue.get());
-        if (obj->IsNode())
-          pNodeList->Append(obj->AsNode());
+  if (maybeResult.has_value()) {
+    if (maybeResult.value().type ==
+        CFXJSE_Engine::ResolveResult::Type::kNodes) {
+      for (auto& pObject : maybeResult.value().objects) {
+        if (pObject->IsNode())
+          pNodeList->Append(pObject->AsNode());
+      }
+    } else {
+      if (maybeResult.value().script_attribute.callback &&
+          maybeResult.value().script_attribute.eValueType ==
+              XFA_ScriptType::Object) {
+        for (auto& pObject : maybeResult.value().objects) {
+          auto innerValue = std::make_unique<CFXJSE_Value>();
+          CJX_Object* jsObject = pObject->JSObject();
+          (*maybeResult.value().script_attribute.callback)(
+              pIsolate, jsObject, innerValue.get(), false,
+              maybeResult.value().script_attribute.attribute);
+          CXFA_Object* obj = CFXJSE_Engine::ToObject(
+              pScriptContext->GetIsolate(), innerValue.get());
+          if (obj->IsNode())
+            pNodeList->Append(obj->AsNode());
+        }
       }
     }
   }
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index dd88653..ec40e2b 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -40,7 +40,6 @@
 #include "xfa/fxfa/parser/cxfa_present.h"
 #include "xfa/fxfa/parser/cxfa_subform.h"
 #include "xfa/fxfa/parser/cxfa_validate.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
 const XFA_AttributeValue gs_EventActivity[] = {
@@ -438,17 +437,17 @@
   }
   WideString wsExpression = (!pRefNode ? L"$form." : L"") + wsName;
 
-  XFA_ResolveNodeRS resolveNodeRS;
   constexpr uint32_t kStyle = XFA_RESOLVENODE_Children |
                               XFA_RESOLVENODE_Properties |
                               XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
-  if (!pScriptContext->ResolveObjects(pRefNode, wsExpression.AsStringView(),
-                                      &resolveNodeRS, kStyle, nullptr)) {
+  Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+      pScriptContext->ResolveObjects(pRefNode, wsExpression.AsStringView(),
+                                     kStyle);
+  if (!maybeResult.has_value())
     return nullptr;
-  }
 
-  if (resolveNodeRS.dwFlags == XFA_ResolveNodeRS::Type::kNodes) {
-    CXFA_Node* pNode = resolveNodeRS.objects.front()->AsNode();
+  if (maybeResult.value().type == CFXJSE_Engine::ResolveResult::Type::kNodes) {
+    CXFA_Node* pNode = maybeResult.value().objects.front()->AsNode();
     if (pNode && pNode->IsWidgetReady())
       return GetWidgetForNode(pNode);
   }
@@ -638,13 +637,15 @@
     constexpr uint32_t kStyle =
         XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
         XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_ALL;
-    XFA_ResolveNodeRS rs;
-    pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(), &rs,
-                                   kStyle, nullptr);
+    Optional<CFXJSE_Engine::ResolveResult> maybeRS =
+        pScriptContext->ResolveObjects(pWidgetNode, wsRef.AsStringView(),
+                                       kStyle);
     pWidgetNode->DeleteItem(-1, false, false);
-    if (rs.dwFlags != XFA_ResolveNodeRS::Type::kNodes || rs.objects.empty())
+    if (!maybeRS.has_value() ||
+        maybeRS.value().type != CFXJSE_Engine::ResolveResult::Type::kNodes ||
+        maybeRS.value().objects.empty()) {
       continue;
-
+    }
     WideString wsValueRef = item->GetValueRef();
     WideString wsLabelRef = item->GetLabelRef();
     const bool bUseValue = wsLabelRef.IsEmpty() || wsLabelRef == wsValueRef;
@@ -655,7 +656,7 @@
     WideString wsValue;
     WideString wsLabel;
     uint32_t uValueHash = FX_HashCode_GetW(wsValueRef.AsStringView(), false);
-    for (auto& refObject : rs.objects) {
+    for (auto& refObject : maybeRS.value().objects) {
       CXFA_Node* refNode = refObject->AsNode();
       if (!refNode)
         continue;
diff --git a/xfa/fxfa/cxfa_textprovider.cpp b/xfa/fxfa/cxfa_textprovider.cpp
index c08452d..781bb5d 100644
--- a/xfa/fxfa/cxfa_textprovider.cpp
+++ b/xfa/fxfa/cxfa_textprovider.cpp
@@ -30,7 +30,6 @@
 #include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/cxfa_para.h"
 #include "xfa/fxfa/parser/cxfa_value.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
 CXFA_TextProvider::CXFA_TextProvider(CXFA_Node* pNode,
diff --git a/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp
index b679423..68ca498 100644
--- a/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp
+++ b/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp
@@ -34,7 +34,6 @@
 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
 #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 
 namespace {
 
@@ -208,15 +207,16 @@
       if (wsExpr.First(4).EqualsASCII("som(") && wsExpr.Back() == L')')
         wsProcessedTarget = wsExpr.Substr(4, wsExpr.GetLength() - 5);
 
-      XFA_ResolveNodeRS rs;
-      bool bRet = pDocument->GetScriptContext()->ResolveObjects(
-          pPageSetRoot, wsProcessedTarget.AsStringView(), &rs,
+      constexpr uint32_t dwFlag =
           XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
-              XFA_RESOLVENODE_Attributes | XFA_RESOLVENODE_Siblings |
-              XFA_RESOLVENODE_Parent,
-          nullptr);
-      if (bRet && rs.objects.front()->IsNode())
-        return rs.objects.front()->AsNode();
+          XFA_RESOLVENODE_Attributes | XFA_RESOLVENODE_Siblings |
+          XFA_RESOLVENODE_Parent;
+      Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+          pDocument->GetScriptContext()->ResolveObjects(
+              pPageSetRoot, wsProcessedTarget.AsStringView(), dwFlag);
+      if (maybeResult.has_value() &&
+          maybeResult.value().objects.front()->IsNode())
+        return maybeResult.value().objects.front()->AsNode();
     }
     iSplitIndex = iSplitNextIndex.value();
   }
diff --git a/xfa/fxfa/parser/BUILD.gn b/xfa/fxfa/parser/BUILD.gn
index 024eb3e..097e4ab 100644
--- a/xfa/fxfa/parser/BUILD.gn
+++ b/xfa/fxfa/parser/BUILD.gn
@@ -673,8 +673,6 @@
     "xfa_basic_data.h",
     "xfa_document_datamerger_imp.cpp",
     "xfa_document_datamerger_imp.h",
-    "xfa_resolvenode_rs.cpp",
-    "xfa_resolvenode_rs.h",
     "xfa_utils.cpp",
     "xfa_utils.h",
   ]
diff --git a/xfa/fxfa/parser/cxfa_document.cpp b/xfa/fxfa/parser/cxfa_document.cpp
index 3ae9307..0fc6532 100644
--- a/xfa/fxfa/parser/cxfa_document.cpp
+++ b/xfa/fxfa/parser/cxfa_document.cpp
@@ -46,7 +46,6 @@
 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
 #include "xfa/fxfa/parser/cxfa_value.h"
 #include "xfa/fxfa/parser/xfa_document_datamerger_imp.h"
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
 namespace {
@@ -351,18 +350,25 @@
   if (bUpLevel || !wsRef.EqualsASCII("name"))
     dFlags |= (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
 
-  XFA_ResolveNodeRS rs;
-  pDocument->GetScriptContext()->ResolveObjects(
-      pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
-  if (rs.dwFlags == XFA_ResolveNodeRS::Type::kCreateNodeAll ||
-      rs.dwFlags == XFA_ResolveNodeRS::Type::kCreateNodeMidAll ||
-      rs.objects.size() > 1) {
-    return pDocument->GetNotBindNode(rs.objects);
+  Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+      pDocument->GetScriptContext()->ResolveObjectsWithBindNode(
+          pDataScope, wsRef.AsStringView(), dFlags, pTemplateNode);
+  if (!maybeResult.has_value())
+    return nullptr;
+
+  if (maybeResult.value().type ==
+          CFXJSE_Engine::ResolveResult::Type::kCreateNodeAll ||
+      maybeResult.value().type ==
+          CFXJSE_Engine::ResolveResult::Type::kCreateNodeMidAll ||
+      maybeResult.value().objects.size() > 1) {
+    return pDocument->GetNotBindNode(maybeResult.value().objects);
   }
 
-  if (rs.dwFlags == XFA_ResolveNodeRS::Type::kCreateNodeOne) {
-    CXFA_Object* pObject =
-        !rs.objects.empty() ? rs.objects.front().Get() : nullptr;
+  if (maybeResult.value().type ==
+      CFXJSE_Engine::ResolveResult::Type::kCreateNodeOne) {
+    CXFA_Object* pObject = !maybeResult.value().objects.empty()
+                               ? maybeResult.value().objects.front().Get()
+                               : nullptr;
     CXFA_Node* pNode = ToNode(pObject);
     return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr;
   }
@@ -1193,16 +1199,19 @@
                   : WideString();
           uint32_t dFlags =
               XFA_RESOLVENODE_Children | XFA_RESOLVENODE_CreateNode;
-          XFA_ResolveNodeRS rs;
-          pDocument->GetScriptContext()->ResolveObjects(
-              pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
+          Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+              pDocument->GetScriptContext()->ResolveObjectsWithBindNode(
+                  pDataScope, wsRef.AsStringView(), dFlags, pTemplateNode);
           CXFA_Object* pObject =
-              !rs.objects.empty() ? rs.objects.front().Get() : nullptr;
+              maybeResult.has_value() && !maybeResult.value().objects.empty()
+                  ? maybeResult.value().objects.front().Get()
+                  : nullptr;
           pDataNode = ToNode(pObject);
           if (pDataNode) {
             CreateDataBinding(
                 pFormNode, pDataNode,
-                rs.dwFlags == XFA_ResolveNodeRS::Type::kExistNodes);
+                maybeResult.value().type ==
+                    CFXJSE_Engine::ResolveResult::Type::kExistNodes);
           } else {
             FormValueNode_MatchNoneCreateChild(pFormNode);
           }
@@ -1567,13 +1576,14 @@
 
     CXFA_Node* pProtoNode = nullptr;
     if (!wsSOM.IsEmpty()) {
-      uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
-                        XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
-                        XFA_RESOLVENODE_Siblings;
-      XFA_ResolveNodeRS resolveNodeRS;
-      if (m_pScriptContext->ResolveObjects(pUseHrefNode, wsSOM, &resolveNodeRS,
-                                           dwFlag, nullptr)) {
-        auto* pFirstObject = resolveNodeRS.objects.front().Get();
+      constexpr uint32_t dwFlag =
+          XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
+          XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
+          XFA_RESOLVENODE_Siblings;
+      Optional<CFXJSE_Engine::ResolveResult> maybeResult =
+          m_pScriptContext->ResolveObjects(pUseHrefNode, wsSOM, dwFlag);
+      if (maybeResult.has_value()) {
+        auto* pFirstObject = maybeResult.value().objects.front().Get();
         if (pFirstObject && pFirstObject->IsNode())
           pProtoNode = pFirstObject->AsNode();
       }
diff --git a/xfa/fxfa/parser/xfa_resolvenode_rs.cpp b/xfa/fxfa/parser/xfa_resolvenode_rs.cpp
deleted file mode 100644
index fd0fbaf..0000000
--- a/xfa/fxfa/parser/xfa_resolvenode_rs.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2020 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
-
-XFA_ResolveNodeRS::XFA_ResolveNodeRS() = default;
-
-XFA_ResolveNodeRS::~XFA_ResolveNodeRS() = default;
diff --git a/xfa/fxfa/parser/xfa_resolvenode_rs.h b/xfa/fxfa/parser/xfa_resolvenode_rs.h
deleted file mode 100644
index 851c94b..0000000
--- a/xfa/fxfa/parser/xfa_resolvenode_rs.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef XFA_FXFA_PARSER_XFA_RESOLVENODE_RS_H_
-#define XFA_FXFA_PARSER_XFA_RESOLVENODE_RS_H_
-
-#include <vector>
-
-#include "v8/include/cppgc/macros.h"
-#include "v8/include/cppgc/member.h"
-#include "xfa/fxfa/parser/xfa_basic_data.h"
-
-class CXFA_Object;
-
-class XFA_ResolveNodeRS {
-  CPPGC_STACK_ALLOCATED();  // Allow raw/unowned pointers.
-
- public:
-  enum class Type {
-    kNodes,
-    kAttribute,
-    kCreateNodeOne,
-    kCreateNodeAll,
-    kCreateNodeMidAll,
-    kExistNodes,
-  };
-
-  XFA_ResolveNodeRS();
-  ~XFA_ResolveNodeRS();
-
-  Type dwFlags = Type::kNodes;
-  XFA_SCRIPTATTRIBUTEINFO script_attribute;
-
-  // Vector of Member would be correct for stack-based vectors, if
-  // STL worked with cppgc.
-  std::vector<cppgc::Member<CXFA_Object>> objects;
-};
-
-#endif  // XFA_FXFA_PARSER_XFA_RESOLVENODE_RS_H_