CFXJSE_Value removal CL, part 7.

-- Be tolerant of empty values in ReentrantPutObjectPropertyHelper().
-- Allow FXJSE_RetrieveObjectBinding() to accept a wider range
   of inputs, returning nullptr when not appropriate.

Bug: pdfium:1610
Change-Id: Ice4d97b64277c1f186cce14debd053d8f8046e55
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/76490
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 f029eaa..bc7cdc0 100644
--- a/fxjs/fxv8.cpp
+++ b/fxjs/fxv8.cpp
@@ -244,8 +244,7 @@
                                          v8::Local<v8::Object> pObj,
                                          ByteStringView bsUTF8PropertyName,
                                          v8::Local<v8::Value> pValue) {
-  ASSERT(!pValue.IsEmpty());
-  if (pObj.IsEmpty())
+  if (pObj.IsEmpty() || pValue.IsEmpty())
     return false;
 
   v8::TryCatch squash_exceptions(pIsolate);
@@ -258,8 +257,7 @@
                                       v8::Local<v8::Object> pObj,
                                       ByteStringView bsUTF8PropertyName,
                                       v8::Local<v8::Value> pPut) {
-  ASSERT(!pPut.IsEmpty());
-  if (pObj.IsEmpty())
+  if (pObj.IsEmpty() || pPut.IsEmpty())
     return false;
 
   v8::TryCatch squash_exceptions(pIsolate);
diff --git a/fxjs/xfa/cfxjse_context.cpp b/fxjs/xfa/cfxjse_context.cpp
index 5de17cb..3f1abe4 100644
--- a/fxjs/xfa/cfxjse_context.cpp
+++ b/fxjs/xfa/cfxjse_context.cpp
@@ -133,13 +133,11 @@
   hObject->SetAlignedPointerInInternalField(1, nullptr);
 }
 
-CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(
-    v8::Local<v8::Object> hJSObject) {
-  ASSERT(!hJSObject.IsEmpty());
-  if (!hJSObject->IsObject())
+CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local<v8::Value> hValue) {
+  if (!fxv8::IsObject(hValue))
     return nullptr;
 
-  v8::Local<v8::Object> hObject = hJSObject;
+  v8::Local<v8::Object> hObject = hValue.As<v8::Object>();
   if (hObject->InternalFieldCount() != 2 ||
       hObject->GetAlignedPointerFromInternalField(0) == kFXJSEProxyObjectTag) {
     v8::Local<v8::Value> hProtoObject = hObject->GetPrototype();
diff --git a/fxjs/xfa/cfxjse_context.h b/fxjs/xfa/cfxjse_context.h
index 2724809..85c3f31 100644
--- a/fxjs/xfa/cfxjse_context.h
+++ b/fxjs/xfa/cfxjse_context.h
@@ -59,6 +59,6 @@
                                CFXJSE_HostObject* lpNewBinding);
 
 void FXJSE_ClearObjectBinding(v8::Local<v8::Object> hJSObject);
-CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local<v8::Object> hJSObject);
+CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local<v8::Value> hValue);
 
 #endif  // FXJS_XFA_CFXJSE_CONTEXT_H_
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 6f3301d..057de36 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -3128,42 +3128,34 @@
   int32_t iArgIndex = 1;
   int32_t iValueIndex = 0;
   while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) {
-    auto argIndexValue =
-        std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[iArgIndex]);
-    if (argIndexValue->IsArray(info.GetIsolate())) {
-      auto lengthValue = std::make_unique<CFXJSE_Value>();
-      argIndexValue->GetObjectProperty(info.GetIsolate(), "length",
-                                       lengthValue.get());
-      int32_t iLength = lengthValue->ToInteger(info.GetIsolate());
+    v8::Local<v8::Value> argIndexValue = info[iArgIndex];
+    if (fxv8::IsArray(argIndexValue)) {
+      v8::Local<v8::Array> arr = argIndexValue.As<v8::Array>();
+      uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
       if (iLength > 3)
         bStopCounterFlags = true;
 
       iValueIndex += (iLength - 2);
       if (iValueIndex >= iIndex) {
-        auto propertyValue = std::make_unique<CFXJSE_Value>();
-        auto jsObjectValue = std::make_unique<CFXJSE_Value>();
-        auto newPropertyValue = std::make_unique<CFXJSE_Value>();
-        argIndexValue->GetObjectPropertyByIdx(info.GetIsolate(), 1,
-                                              propertyValue.get());
-        argIndexValue->GetObjectPropertyByIdx(
-            info.GetIsolate(), (iLength - 1) - (iValueIndex - iIndex),
-            jsObjectValue.get());
-        if (propertyValue->IsNull(info.GetIsolate())) {
-          if (jsObjectValue->IsObject(info.GetIsolate())) {
-            newPropertyValue->ForceSetValue(
-                info.GetIsolate(),
-                GetObjectDefaultValue(info.GetIsolate(),
-                                      jsObjectValue->GetValue(info.GetIsolate())
-                                          .As<v8::Object>()));
+        v8::Local<v8::Value> propertyValue =
+            fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
+        v8::Local<v8::Value> jsValue = fxv8::ReentrantGetArrayElementHelper(
+            info.GetIsolate(), arr, (iLength - 1) - (iValueIndex - iIndex));
+        v8::Local<v8::Value> newPropertyValue;
+        if (fxv8::IsObject(jsValue)) {
+          v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
+          if (fxv8::IsNull(propertyValue)) {
+            newPropertyValue =
+                GetObjectDefaultValue(info.GetIsolate(), jsObjectValue);
+          } else {
+            ByteString bsName = fxv8::ReentrantToByteStringHelper(
+                info.GetIsolate(), propertyValue);
+            newPropertyValue = fxv8::ReentrantGetObjectPropertyHelper(
+                info.GetIsolate(), jsObjectValue, bsName.AsStringView());
           }
-        } else {
-          jsObjectValue->GetObjectProperty(
-              info.GetIsolate(),
-              propertyValue->ToString(info.GetIsolate()).AsStringView(),
-              newPropertyValue.get());
         }
-        ByteString bsChosen = ValueToUTF8String(
-            info.GetIsolate(), newPropertyValue->GetValue(info.GetIsolate()));
+        ByteString bsChosen =
+            ValueToUTF8String(info.GetIsolate(), newPropertyValue);
         info.GetReturnValue().Set(
             fxv8::NewStringHelper(info.GetIsolate(), bsChosen.AsStringView()));
         bFound = true;
@@ -3171,8 +3163,8 @@
     } else {
       iValueIndex++;
       if (iValueIndex == iIndex) {
-        ByteString bsChosen = ValueToUTF8String(
-            info.GetIsolate(), argIndexValue->GetValue(info.GetIsolate()));
+        ByteString bsChosen =
+            ValueToUTF8String(info.GetIsolate(), argIndexValue);
         info.GetReturnValue().Set(
             fxv8::NewStringHelper(info.GetIsolate(), bsChosen.AsStringView()));
         bFound = true;
@@ -3192,9 +3184,7 @@
     ToFormCalcContext(pThis)->ThrowParamCountMismatchException(L"Exists");
     return;
   }
-  auto temp = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[0]);
-  info.GetReturnValue().Set(
-      static_cast<int>(temp->IsObject(info.GetIsolate())));
+  info.GetReturnValue().Set(fxv8::IsObject(info[0]));
 }
 
 // static
@@ -3334,55 +3324,40 @@
     return;
   }
 
-  auto argOne = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[0]);
-  if (!argOne->IsArray(info.GetIsolate()) &&
-      !argOne->IsObject(info.GetIsolate()) &&
-      !argOne->IsBoolean(info.GetIsolate()) &&
-      !argOne->IsString(info.GetIsolate()) &&
-      !argOne->IsNull(info.GetIsolate()) &&
-      !argOne->IsNumber(info.GetIsolate())) {
+  v8::Local<v8::Value> argOne = info[0];
+  if (fxv8::IsBoolean(argOne) || fxv8::IsString(argOne) ||
+      fxv8::IsNumber(argOne)) {
+    info.GetReturnValue().Set(argOne);
+    return;
+  }
+
+  std::vector<v8::Local<v8::Value>> values(3);
+  int intVal = 3;
+  if (fxv8::IsNull(argOne)) {
+    // TODO(dsinclair): Why is this 4 when the others are all 3?
+    intVal = 4;
+    values[2] = fxv8::NewNullHelper(info.GetIsolate());
+  } else if (fxv8::IsArray(argOne)) {
+    v8::Local<v8::Array> arr = argOne.As<v8::Array>();
+    v8::Local<v8::Value> propertyValue =
+        fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
+    v8::Local<v8::Value> jsObjectValue =
+        fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2);
+    if (!fxv8::IsNull(propertyValue) || fxv8::IsNull(jsObjectValue)) {
+      pContext->ThrowArgumentMismatchException();
+      return;
+    }
+    values[2] = jsObjectValue;
+  } else if (fxv8::IsObject(argOne)) {
+    values[2] = argOne;
+  } else {
     pContext->ThrowArgumentMismatchException();
     return;
   }
 
-  if (argOne->IsBoolean(info.GetIsolate()) ||
-      argOne->IsString(info.GetIsolate()) ||
-      argOne->IsNumber(info.GetIsolate())) {
-    info.GetReturnValue().Set(argOne->DirectGetValue());
-    return;
-  }
-
-  std::vector<std::unique_ptr<CFXJSE_Value>> values;
-  for (int32_t i = 0; i < 3; i++)
-    values.push_back(std::make_unique<CFXJSE_Value>());
-
-  int intVal = 3;
-  if (argOne->IsNull(info.GetIsolate())) {
-    // TODO(dsinclair): Why is this 4 when the others are all 3?
-    intVal = 4;
-    values[2]->SetNull(info.GetIsolate());
-  } else if (argOne->IsArray(info.GetIsolate())) {
-    auto propertyValue = std::make_unique<CFXJSE_Value>();
-    auto jsObjectValue = std::make_unique<CFXJSE_Value>();
-    argOne->GetObjectPropertyByIdx(info.GetIsolate(), 1, propertyValue.get());
-    argOne->GetObjectPropertyByIdx(info.GetIsolate(), 2, jsObjectValue.get());
-    if (!propertyValue->IsNull(info.GetIsolate()) ||
-        jsObjectValue->IsNull(info.GetIsolate())) {
-      pContext->ThrowArgumentMismatchException();
-      return;
-    }
-
-    values[2]->Assign(info.GetIsolate(), jsObjectValue.get());
-  } else if (argOne->IsObject(info.GetIsolate())) {
-    values[2]->Assign(info.GetIsolate(), argOne.get());
-  }
-
-  values[0]->SetInteger(info.GetIsolate(), intVal);
-  values[1]->SetNull(info.GetIsolate());
-
-  auto temp = std::make_unique<CFXJSE_Value>();
-  temp->SetArray(info.GetIsolate(), values);
-  info.GetReturnValue().Set(temp->DirectGetValue());
+  values[0] = fxv8::NewNumberHelper(info.GetIsolate(), intVal);
+  values[1] = fxv8::NewNullHelper(info.GetIsolate());
+  info.GetReturnValue().Set(fxv8::NewArrayHelper(info.GetIsolate(), values));
 }
 
 // static
@@ -4655,55 +4630,48 @@
 void CFXJSE_FormCalcContext::assign_value_operator(
     CFXJSE_HostObject* pThis,
     const v8::FunctionCallbackInfo<v8::Value>& info) {
+  v8::Isolate* pIsolate = info.GetIsolate();
   CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
   if (info.Length() != 2) {
     pContext->ThrowCompilerErrorException();
     return;
   }
   ByteStringView bsFuncName("asgn_val_op");
-  auto lValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[0]);
-  auto rValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(),
-                                               GetSimpleValue(info, 1));
-  if (lValue->IsArray(info.GetIsolate())) {
-    v8::Isolate* pIsolate = pContext->GetIsolate();
-    auto leftLengthValue = std::make_unique<CFXJSE_Value>();
-    lValue->GetObjectProperty(info.GetIsolate(), "length",
-                              leftLengthValue.get());
-    int32_t iLeftLength = leftLengthValue->ToInteger(info.GetIsolate());
-    auto jsObjectValue = std::make_unique<CFXJSE_Value>();
-    auto propertyValue = std::make_unique<CFXJSE_Value>();
-    lValue->GetObjectPropertyByIdx(info.GetIsolate(), 1, propertyValue.get());
-    if (propertyValue->IsNull(info.GetIsolate())) {
-      for (int32_t i = 2; i < iLeftLength; i++) {
-        lValue->GetObjectPropertyByIdx(info.GetIsolate(), i,
-                                       jsObjectValue.get());
-        if (!jsObjectValue->IsObject(info.GetIsolate()) ||
-            !SetObjectDefaultValue(
-                info.GetIsolate(),
-                jsObjectValue->GetValue(info.GetIsolate()).As<v8::Object>(),
-                rValue->GetValue(info.GetIsolate()))) {
+  v8::Local<v8::Value> lValue = info[0];
+  v8::Local<v8::Value> rValue = GetSimpleValue(info, 1);
+  if (fxv8::IsArray(lValue)) {
+    v8::Local<v8::Array> arr = lValue.As<v8::Array>();
+    uint32_t iLeftLength = fxv8::GetArrayLengthHelper(arr);
+    v8::Local<v8::Value> propertyValue =
+        fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 1);
+    for (uint32_t i = 2; i < iLeftLength; i++) {
+      v8::Local<v8::Value> jsValue =
+          fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, i);
+      if (!fxv8::IsObject(jsValue)) {
+        pContext->ThrowNoDefaultPropertyException(bsFuncName);
+        return;
+      }
+      v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
+      if (fxv8::IsNull(propertyValue)) {
+        if (!SetObjectDefaultValue(pIsolate, jsObjectValue, rValue)) {
           pContext->ThrowNoDefaultPropertyException(bsFuncName);
           return;
         }
-      }
-    } else {
-      for (int32_t i = 2; i < iLeftLength; i++) {
-        lValue->GetObjectPropertyByIdx(pIsolate, i, jsObjectValue.get());
-        jsObjectValue->SetObjectProperty(
-            info.GetIsolate(), propertyValue->ToString(pIsolate).AsStringView(),
-            rValue.get());
+      } else {
+        fxv8::ReentrantPutObjectPropertyHelper(
+            pIsolate, jsObjectValue,
+            fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue)
+                .AsStringView(),
+            rValue);
       }
     }
-  } else if (lValue->IsObject(info.GetIsolate())) {
-    if (!SetObjectDefaultValue(
-            info.GetIsolate(),
-            lValue->GetValue(info.GetIsolate()).As<v8::Object>(),
-            rValue->GetValue(info.GetIsolate()))) {
+  } else if (fxv8::IsObject(lValue)) {
+    if (!SetObjectDefaultValue(pIsolate, lValue.As<v8::Object>(), rValue)) {
       pContext->ThrowNoDefaultPropertyException(bsFuncName);
       return;
     }
   }
-  info.GetReturnValue().Set(rValue->DirectGetValue());
+  info.GetReturnValue().Set(rValue);
 }
 
 // static
@@ -4820,31 +4788,32 @@
 bool CFXJSE_FormCalcContext::fm_ref_equal(
     CFXJSE_HostObject* pThis,
     const v8::FunctionCallbackInfo<v8::Value>& info) {
-  auto argFirst = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[0]);
-  auto argSecond = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[1]);
-  if (!argFirst->IsArray(info.GetIsolate()) ||
-      !argSecond->IsArray(info.GetIsolate()))
+  v8::Local<v8::Value> argFirst = info[0];
+  v8::Local<v8::Value> argSecond = info[1];
+  if (!fxv8::IsArray(argFirst) || !fxv8::IsArray(argSecond))
     return false;
 
-  auto firstFlagValue = std::make_unique<CFXJSE_Value>();
-  auto secondFlagValue = std::make_unique<CFXJSE_Value>();
-  argFirst->GetObjectPropertyByIdx(info.GetIsolate(), 0, firstFlagValue.get());
-  argSecond->GetObjectPropertyByIdx(info.GetIsolate(), 0,
-                                    secondFlagValue.get());
-  if (firstFlagValue->ToInteger(info.GetIsolate()) != 3 ||
-      secondFlagValue->ToInteger(info.GetIsolate()) != 3)
+  v8::Local<v8::Array> firstArr = argFirst.As<v8::Array>();
+  v8::Local<v8::Array> secondArr = argSecond.As<v8::Array>();
+  v8::Local<v8::Value> firstFlag =
+      fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), firstArr, 0);
+  v8::Local<v8::Value> secondFlag =
+      fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), secondArr, 0);
+  if (fxv8::ReentrantToInt32Helper(info.GetIsolate(), firstFlag) != 3 ||
+      fxv8::ReentrantToInt32Helper(info.GetIsolate(), secondFlag) != 3) {
+    return false;
+  }
+
+  v8::Local<v8::Value> firstValue =
+      fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), firstArr, 2);
+  v8::Local<v8::Value> secondValue =
+      fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), secondArr, 2);
+
+  if (fxv8::IsNull(firstValue) || fxv8::IsNull(secondValue))
     return false;
 
-  auto firstJSObject = std::make_unique<CFXJSE_Value>();
-  auto secondJSObject = std::make_unique<CFXJSE_Value>();
-  argFirst->GetObjectPropertyByIdx(info.GetIsolate(), 2, firstJSObject.get());
-  argSecond->GetObjectPropertyByIdx(info.GetIsolate(), 2, secondJSObject.get());
-  if (firstJSObject->IsNull(info.GetIsolate()) ||
-      secondJSObject->IsNull(info.GetIsolate()))
-    return false;
-
-  return firstJSObject->ToHostObject(info.GetIsolate()) ==
-         secondJSObject->ToHostObject(info.GetIsolate());
+  return FXJSE_RetrieveObjectBinding(firstValue) ==
+         FXJSE_RetrieveObjectBinding(secondValue);
 }
 
 // static