Remove CFXJSE_Value from CFXJSE_FormCalcContext::DotAccessorCommon().

Bug: pdfium:1610
Change-Id: I211383cd45dfa54d2ffe22e95cf7e9d47dbfb735
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/76422
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
diff --git a/fxjs/fxv8.cpp b/fxjs/fxv8.cpp
index 6a952b0..f029eaa 100644
--- a/fxjs/fxv8.cpp
+++ b/fxjs/fxv8.cpp
@@ -88,6 +88,17 @@
   return v8::Array::New(pIsolate);
 }
 
+v8::Local<v8::Array> NewArrayHelper(v8::Isolate* pIsolate,
+                                    pdfium::span<v8::Local<v8::Value>> values) {
+  v8::Local<v8::Array> result = NewArrayHelper(pIsolate);
+  for (size_t i = 0; i < values.size(); ++i) {
+    fxv8::ReentrantPutArrayElementHelper(
+        pIsolate, result, i,
+        values[i].IsEmpty() ? fxv8::NewUndefinedHelper(pIsolate) : values[i]);
+  }
+  return result;
+}
+
 v8::Local<v8::Object> NewObjectHelper(v8::Isolate* pIsolate) {
   return v8::Object::New(pIsolate);
 }
diff --git a/fxjs/fxv8.h b/fxjs/fxv8.h
index 5e492c2..00c5a8a 100644
--- a/fxjs/fxv8.h
+++ b/fxjs/fxv8.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "core/fxcrt/fx_string.h"
+#include "third_party/base/span.h"
 #include "v8/include/v8.h"
 
 // The fxv8 functions soften up the interface to the V8 API.
@@ -39,6 +40,8 @@
 v8::Local<v8::String> NewStringHelper(v8::Isolate* pIsolate,
                                       WideStringView str);
 v8::Local<v8::Array> NewArrayHelper(v8::Isolate* pIsolate);
+v8::Local<v8::Array> NewArrayHelper(v8::Isolate* pIsolate,
+                                    pdfium::span<v8::Local<v8::Value>> values);
 v8::Local<v8::Object> NewObjectHelper(v8::Isolate* pIsolate);
 v8::Local<v8::Date> NewDateHelper(v8::Isolate* pIsolate, double d);
 
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index becf069..99d7ca1 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -1551,33 +1551,32 @@
   return results;
 }
 
-bool GetObjectForName(CFXJSE_HostObject* pHostObject,
-                      CFXJSE_Value* accessorValue,
-                      ByteStringView bsAccessorName) {
+// Returns empty value on failure.
+v8::Local<v8::Value> GetObjectForName(CFXJSE_HostObject* pHostObject,
+                                      ByteStringView bsAccessorName) {
   CXFA_Document* pDoc = ToFormCalcContext(pHostObject)->GetDocument();
   if (!pDoc)
-    return false;
+    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;
-  bool bRet = pScriptContext->ResolveObjects(
-      pScriptContext->GetThisObject(),
-      WideString::FromUTF8(bsAccessorName).AsStringView(), &resolveNodeRS,
-      dwFlags, nullptr);
-  if (bRet && resolveNodeRS.dwFlags == XFA_ResolveNodeRS::Type::kNodes) {
-    v8::Isolate* pIsolate = ToFormCalcContext(pHostObject)->GetIsolate();
-    accessorValue->ForceSetValue(pIsolate,
-                                 pScriptContext->GetOrCreateJSBindingFromMap(
-                                     resolveNodeRS.objects.front().Get()));
-    return true;
+  if (!pScriptContext->ResolveObjects(
+          pScriptContext->GetThisObject(),
+          WideString::FromUTF8(bsAccessorName).AsStringView(), &resolveNodeRS,
+          dwFlags, /*bindNode=*/nullptr)) {
+    return v8::Local<v8::Value>();
   }
-  return false;
+  if (resolveNodeRS.dwFlags != XFA_ResolveNodeRS::Type::kNodes)
+    return v8::Local<v8::Value>();
+
+  return pScriptContext->GetOrCreateJSBindingFromMap(
+      resolveNodeRS.objects.front().Get());
 }
 
 bool ResolveObjects(CFXJSE_HostObject* pHostObject,
-                    CFXJSE_Value* pRefValue,
+                    v8::Local<v8::Value> pRefValue,
                     ByteStringView bsSomExp,
                     XFA_ResolveNodeRS* resolveNodeRS,
                     bool bDotAccessor,
@@ -1592,7 +1591,7 @@
   CXFA_Object* pNode = nullptr;
   uint32_t dFlags = 0UL;
   if (bDotAccessor) {
-    if (pRefValue && pRefValue->IsNull(pIsolate)) {
+    if (fxv8::IsNull(pRefValue)) {
       pNode = pScriptContext->GetThisObject();
       dFlags = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
     } else {
@@ -1628,14 +1627,11 @@
                                         resolveNodeRS, dFlags, nullptr);
 }
 
-void ParseResolveResult(
-    CFXJSE_HostObject* pHostObject,
-    const XFA_ResolveNodeRS& resolveNodeRS,
-    CFXJSE_Value* pParentValue,
-    std::vector<std::unique_ptr<CFXJSE_Value>>* resultValues,
-    bool* bAttribute) {
-  ASSERT(bAttribute);
-
+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();
 
   CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pHostObject);
@@ -1645,9 +1641,8 @@
     *bAttribute = false;
     CFXJSE_Engine* pScriptContext = pContext->GetDocument()->GetScriptContext();
     for (auto& pObject : resolveNodeRS.objects) {
-      resultValues->push_back(std::make_unique<CFXJSE_Value>());
-      resultValues->back()->ForceSetValue(
-          pIsolate, pScriptContext->GetOrCreateJSBindingFromMap(pObject.Get()));
+      resultValues->push_back(
+          pScriptContext->GetOrCreateJSBindingFromMap(pObject.Get()));
     }
     return;
   }
@@ -1661,17 +1656,12 @@
       (*resolveNodeRS.script_attribute.callback)(
           pIsolate, jsObject, pValue.get(), false,
           resolveNodeRS.script_attribute.attribute);
-      resultValues->push_back(std::move(pValue));
+      resultValues->push_back(pValue->GetValue(pIsolate));
       *bAttribute = false;
     }
   }
-  if (!*bAttribute)
-    return;
-  if (!pParentValue || !pParentValue->IsObject(pIsolate))
-    return;
-
-  resultValues->push_back(std::make_unique<CFXJSE_Value>());
-  resultValues->back()->Assign(pIsolate, pParentValue);
+  if (*bAttribute && fxv8::IsObject(pParentValue))
+    resultValues->push_back(pParentValue);
 }
 
 }  // namespace
@@ -5427,29 +5417,26 @@
       fxv8::ReentrantToInt32Helper(info.GetIsolate(), info[3]), iIndexValue,
       bIsStar);
 
-  auto argAccessor = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[0]);
-  if (argAccessor->IsArray(info.GetIsolate())) {
-    auto pLengthValue = std::make_unique<CFXJSE_Value>();
-    argAccessor->GetObjectProperty(info.GetIsolate(), "length",
-                                   pLengthValue.get());
-    int32_t iLength = pLengthValue->ToInteger(info.GetIsolate());
+  v8::Local<v8::Value> argAccessor = info[0];
+  if (fxv8::IsArray(argAccessor)) {
+    v8::Local<v8::Array> arr = argAccessor.As<v8::Array>();
+    uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
     if (iLength < 3) {
       pContext->ThrowArgumentMismatchException();
       return;
     }
 
-    auto hJSObjValue = std::make_unique<CFXJSE_Value>();
-    std::vector<std::vector<std::unique_ptr<CFXJSE_Value>>> resolveValues(
-        iLength - 2);
+    std::vector<std::vector<v8::Local<v8::Value>>> resolveValues(iLength - 2);
     bool bAttribute = false;
     bool bAllEmpty = true;
-    for (int32_t i = 2; i < iLength; i++) {
-      argAccessor->GetObjectPropertyByIdx(info.GetIsolate(), i,
-                                          hJSObjValue.get());
+    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.get(), bsSomExp.AsStringView(),
+      if (ResolveObjects(pThis, hJSObjValue, bsSomExp.AsStringView(),
                          &resolveNodeRS, bDotAccessor, bHasNoResolveName)) {
-        ParseResolveResult(pThis, resolveNodeRS, hJSObjValue.get(),
+        ParseResolveResult(pThis, resolveNodeRS, hJSObjValue,
                            &resolveValues[i - 2], &bAttribute);
         bAllEmpty = bAllEmpty && resolveValues[i - 2].empty();
       }
@@ -5470,10 +5457,10 @@
     else
       values.back()->SetNull(pIsolate);
 
-    for (int32_t i = 0; i < iLength - 2; i++) {
+    for (uint32_t i = 0; i < iLength - 2; i++) {
       for (size_t j = 0; j < resolveValues[i].size(); j++) {
-        values.push_back(std::make_unique<CFXJSE_Value>());
-        values.back()->Assign(pIsolate, resolveValues[i][j].get());
+        values.push_back(
+            std::make_unique<CFXJSE_Value>(pIsolate, resolveValues[i][j]));
       }
     }
     auto pReturn = std::make_unique<CFXJSE_Value>();
@@ -5486,15 +5473,18 @@
   bool bRet = false;
   ByteString bsAccessorName =
       fxv8::ReentrantToByteStringHelper(info.GetIsolate(), info[1]);
-  if (argAccessor->IsObject(pIsolate) ||
-      (argAccessor->IsNull(pIsolate) && bsAccessorName.IsEmpty())) {
-    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
+  if (fxv8::IsObject(argAccessor) ||
+      (fxv8::IsNull(argAccessor) && bsAccessorName.IsEmpty())) {
+    bRet = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
                           &resolveNodeRS, bDotAccessor, bHasNoResolveName);
-  } else if (!argAccessor->IsObject(pIsolate) && !bsAccessorName.IsEmpty() &&
-             GetObjectForName(pThis, argAccessor.get(),
-                              bsAccessorName.AsStringView())) {
-    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
-                          &resolveNodeRS, 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);
+    }
   }
   if (!bRet) {
     pContext->ThrowPropertyNotInObjectException(
@@ -5503,27 +5493,22 @@
     return;
   }
 
-  std::vector<std::unique_ptr<CFXJSE_Value>> resolveValues;
+  std::vector<v8::Local<v8::Value>> resolveValues;
   bool bAttribute = false;
-  ParseResolveResult(pThis, resolveNodeRS, argAccessor.get(), &resolveValues,
+  ParseResolveResult(pThis, resolveNodeRS, argAccessor, &resolveValues,
                      &bAttribute);
 
-  std::vector<std::unique_ptr<CFXJSE_Value>> values;
-  for (size_t i = 0; i < resolveValues.size() + 2; i++)
-    values.push_back(std::make_unique<CFXJSE_Value>());
-
-  values[0]->SetInteger(pIsolate, 1);
-  if (bAttribute)
-    values[1]->SetString(pIsolate, bsName.AsStringView());
-  else
-    values[1]->SetNull(pIsolate);
+  std::vector<v8::Local<v8::Value>> values(resolveValues.size() + 2);
+  values[0] = fxv8::NewNumberHelper(pIsolate, 1);
+  values[1] = bAttribute
+                  ? fxv8::NewStringHelper(pIsolate, bsName.AsStringView())
+                        .As<v8::Value>()
+                  : fxv8::NewNullHelper(pIsolate).As<v8::Value>();
 
   for (size_t i = 0; i < resolveValues.size(); i++)
-    values[i + 2]->Assign(pIsolate, resolveValues[i].get());
+    values[i + 2] = resolveValues[i];
 
-  auto pReturn = std::make_unique<CFXJSE_Value>();
-  pReturn->SetArray(pIsolate, values);
-  info.GetReturnValue().Set(pReturn->DirectGetValue());
+  info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, values));
 }
 
 bool CFXJSE_FormCalcContext::ApplyToExpansion(