Add CFXJSE_FormCalcContext::DotAccessorCommon().

Combine the nearly identical code from dot_accessor() and
dotdot_accessor().

Change-Id: I974675c74738783552fe7a62e68ee3b590901e11
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52051
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index b3a5e06..9651ac8 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -4976,236 +4976,14 @@
 void CFXJSE_FormCalcContext::dot_accessor(CFXJSE_Value* pThis,
                                           ByteStringView bsFuncName,
                                           CFXJSE_Arguments& args) {
-  CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
-  v8::Isolate* pIsolate = pContext->GetScriptRuntime();
-  int32_t argc = args.GetLength();
-  if (argc < 4 || argc > 5) {
-    pContext->ThrowCompilerErrorException();
-    return;
-  }
-
-  bool bIsStar = true;
-  int32_t iIndexValue = 0;
-  if (argc > 4) {
-    bIsStar = false;
-    iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
-  }
-
-  ByteString bsName = args.GetUTF8String(2);
-  ByteString bsSomExp = GenerateSomExpression(
-      bsName.AsStringView(), args.GetInt32(3), iIndexValue, bIsStar);
-
-  std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
-  if (argAccessor->IsArray()) {
-    auto pLengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate);
-    argAccessor->GetObjectProperty("length", pLengthValue.get());
-    int32_t iLength = pLengthValue->ToInteger();
-    if (iLength < 3) {
-      pContext->ThrowArgumentMismatchException();
-      return;
-    }
-
-    auto hJSObjValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate);
-    std::vector<std::vector<std::unique_ptr<CFXJSE_Value>>> resolveValues(
-        iLength - 2);
-    bool bAttribute = false;
-    int32_t iCounter = 0;
-    for (int32_t i = 2; i < iLength; i++) {
-      argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
-
-      XFA_RESOLVENODE_RS resolveNodeRS;
-      if (ResolveObjects(pThis, hJSObjValue.get(), bsSomExp.AsStringView(),
-                         &resolveNodeRS, true, bsName.IsEmpty())) {
-        ParseResolveResult(pThis, resolveNodeRS, hJSObjValue.get(),
-                           &resolveValues[i - 2], &bAttribute);
-        iCounter += resolveValues[i - 2].size();
-      }
-    }
-    if (iCounter < 1) {
-      pContext->ThrowPropertyNotInObjectException(
-          WideString::FromUTF8(bsName.AsStringView()),
-          WideString::FromUTF8(bsSomExp.AsStringView()));
-      return;
-    }
-
-    std::vector<std::unique_ptr<CFXJSE_Value>> values;
-    for (int32_t i = 0; i < iCounter + 2; i++)
-      values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate));
-
-    values[0]->SetInteger(1);
-    if (bAttribute)
-      values[1]->SetString(bsName.AsStringView());
-    else
-      values[1]->SetNull();
-
-    int32_t iIndex = 2;
-    for (int32_t i = 0; i < iLength - 2; i++) {
-      for (size_t j = 0; j < resolveValues[i].size(); j++) {
-        values[iIndex]->Assign(resolveValues[i][j].get());
-        iIndex++;
-      }
-    }
-    args.GetReturnValue()->SetArray(values);
-    return;
-  }
-
-  XFA_RESOLVENODE_RS resolveNodeRS;
-  bool bRet = false;
-  ByteString bsAccessorName = args.GetUTF8String(1);
-  if (argAccessor->IsObject() ||
-      (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
-    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
-                          &resolveNodeRS, true, bsName.IsEmpty());
-  } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
-             GetObjectForName(pThis, argAccessor.get(),
-                              bsAccessorName.AsStringView())) {
-    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
-                          &resolveNodeRS, true, bsName.IsEmpty());
-  }
-  if (!bRet) {
-    pContext->ThrowPropertyNotInObjectException(
-        WideString::FromUTF8(bsName.AsStringView()),
-        WideString::FromUTF8(bsSomExp.AsStringView()));
-    return;
-  }
-
-  std::vector<std::unique_ptr<CFXJSE_Value>> resolveValues;
-  bool bAttribute = false;
-  ParseResolveResult(pThis, resolveNodeRS, argAccessor.get(), &resolveValues,
-                     &bAttribute);
-
-  std::vector<std::unique_ptr<CFXJSE_Value>> values;
-  for (size_t i = 0; i < resolveValues.size() + 2; i++)
-    values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate));
-
-  values[0]->SetInteger(1);
-  if (bAttribute)
-    values[1]->SetString(bsName.AsStringView());
-  else
-    values[1]->SetNull();
-
-  for (size_t i = 0; i < resolveValues.size(); i++)
-    values[i + 2]->Assign(resolveValues[i].get());
-
-  args.GetReturnValue()->SetArray(values);
+  DotAccessorCommon(pThis, bsFuncName, args, /*bDotAccessor=*/true);
 }
 
 // static
 void CFXJSE_FormCalcContext::dotdot_accessor(CFXJSE_Value* pThis,
                                              ByteStringView bsFuncName,
                                              CFXJSE_Arguments& args) {
-  CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
-  v8::Isolate* pIsolate = pContext->GetScriptRuntime();
-  int32_t argc = args.GetLength();
-  if (argc < 4 || argc > 5) {
-    pContext->ThrowCompilerErrorException();
-    return;
-  }
-
-  bool bIsStar = true;
-  int32_t iIndexValue = 0;
-  if (argc > 4) {
-    bIsStar = false;
-    iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
-  }
-
-  ByteString bsName = args.GetUTF8String(2);
-  ByteString bsSomExp = GenerateSomExpression(
-      bsName.AsStringView(), args.GetInt32(3), iIndexValue, bIsStar);
-
-  std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
-  if (argAccessor->IsArray()) {
-    auto pLengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate);
-    argAccessor->GetObjectProperty("length", pLengthValue.get());
-    int32_t iLength = pLengthValue->ToInteger();
-    if (iLength < 3) {
-      pContext->ThrowArgumentMismatchException();
-      return;
-    }
-
-    int32_t iCounter = 0;
-
-    std::vector<std::vector<std::unique_ptr<CFXJSE_Value>>> resolveValues(
-        iLength - 2);
-    auto hJSObjValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate);
-    bool bAttribute = false;
-    for (int32_t i = 2; i < iLength; i++) {
-      argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
-      XFA_RESOLVENODE_RS resolveNodeRS;
-      if (ResolveObjects(pThis, hJSObjValue.get(), bsSomExp.AsStringView(),
-                         &resolveNodeRS, false, false)) {
-        ParseResolveResult(pThis, resolveNodeRS, hJSObjValue.get(),
-                           &resolveValues[i - 2], &bAttribute);
-        iCounter += resolveValues[i - 2].size();
-      }
-    }
-    if (iCounter < 1) {
-      pContext->ThrowPropertyNotInObjectException(
-          WideString::FromUTF8(bsName.AsStringView()),
-          WideString::FromUTF8(bsSomExp.AsStringView()));
-      return;
-    }
-
-    std::vector<std::unique_ptr<CFXJSE_Value>> values;
-    for (int32_t i = 0; i < iCounter + 2; i++)
-      values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate));
-
-    values[0]->SetInteger(1);
-    if (bAttribute)
-      values[1]->SetString(bsName.AsStringView());
-    else
-      values[1]->SetNull();
-
-    int32_t iIndex = 2;
-    for (int32_t i = 0; i < iLength - 2; i++) {
-      for (size_t j = 0; j < resolveValues[i].size(); j++) {
-        values[iIndex]->Assign(resolveValues[i][j].get());
-        iIndex++;
-      }
-    }
-    args.GetReturnValue()->SetArray(values);
-    return;
-  }
-
-  XFA_RESOLVENODE_RS resolveNodeRS;
-  bool bRet = false;
-  ByteString bsAccessorName = args.GetUTF8String(1);
-  if (argAccessor->IsObject() ||
-      (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
-    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
-                          &resolveNodeRS, false, false);
-  } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
-             GetObjectForName(pThis, argAccessor.get(),
-                              bsAccessorName.AsStringView())) {
-    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
-                          &resolveNodeRS, false, false);
-  }
-  if (!bRet) {
-    pContext->ThrowPropertyNotInObjectException(
-        WideString::FromUTF8(bsName.AsStringView()),
-        WideString::FromUTF8(bsSomExp.AsStringView()));
-    return;
-  }
-
-  std::vector<std::unique_ptr<CFXJSE_Value>> resolveValues;
-  bool bAttribute = false;
-  ParseResolveResult(pThis, resolveNodeRS, argAccessor.get(), &resolveValues,
-                     &bAttribute);
-
-  std::vector<std::unique_ptr<CFXJSE_Value>> values;
-  for (size_t i = 0; i < resolveValues.size() + 2; i++)
-    values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate));
-
-  values[0]->SetInteger(1);
-  if (bAttribute)
-    values[1]->SetString(bsName.AsStringView());
-  else
-    values[1]->SetNull();
-
-  for (size_t i = 0; i < resolveValues.size(); i++)
-    values[i + 2]->Assign(resolveValues[i].get());
-
-  args.GetReturnValue()->SetArray(values);
+  DotAccessorCommon(pThis, bsFuncName, args, /*bDotAccessor=*/false);
 }
 
 // static
@@ -5678,7 +5456,7 @@
                                             CFXJSE_Value* pRefValue,
                                             ByteStringView bsSomExp,
                                             XFA_RESOLVENODE_RS* resolveNodeRS,
-                                            bool bdotAccessor,
+                                            bool bDotAccessor,
                                             bool bHasNoResolveName) {
   CXFA_Document* pDoc = ToFormCalcContext(pThis)->GetDocument();
   if (!pDoc)
@@ -5688,7 +5466,7 @@
   CFXJSE_Engine* pScriptContext = pDoc->GetScriptContext();
   CXFA_Object* pNode = nullptr;
   uint32_t dFlags = 0UL;
-  if (bdotAccessor) {
+  if (bDotAccessor) {
     if (pRefValue && pRefValue->IsNull()) {
       pNode = pScriptContext->GetThisObject();
       dFlags = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
@@ -5956,6 +5734,125 @@
   pValue->Assign(m_pValue.get());
 }
 
+// static
+void CFXJSE_FormCalcContext::DotAccessorCommon(CFXJSE_Value* pThis,
+                                               ByteStringView bsFuncName,
+                                               CFXJSE_Arguments& args,
+                                               bool bDotAccessor) {
+  CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
+  v8::Isolate* pIsolate = pContext->GetScriptRuntime();
+  int32_t argc = args.GetLength();
+  if (argc < 4 || argc > 5) {
+    pContext->ThrowCompilerErrorException();
+    return;
+  }
+
+  bool bIsStar = true;
+  int32_t iIndexValue = 0;
+  if (argc > 4) {
+    bIsStar = false;
+    iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
+  }
+
+  const ByteString bsName = args.GetUTF8String(2);
+  const bool bHasNoResolveName = bDotAccessor && bsName.IsEmpty();
+  ByteString bsSomExp = GenerateSomExpression(
+      bsName.AsStringView(), args.GetInt32(3), iIndexValue, bIsStar);
+
+  std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
+  if (argAccessor->IsArray()) {
+    auto pLengthValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate);
+    argAccessor->GetObjectProperty("length", pLengthValue.get());
+    int32_t iLength = pLengthValue->ToInteger();
+    if (iLength < 3) {
+      pContext->ThrowArgumentMismatchException();
+      return;
+    }
+
+    int32_t iCounter = 0;
+    auto hJSObjValue = pdfium::MakeUnique<CFXJSE_Value>(pIsolate);
+    std::vector<std::vector<std::unique_ptr<CFXJSE_Value>>> resolveValues(
+        iLength - 2);
+    bool bAttribute = false;
+    for (int32_t i = 2; i < iLength; i++) {
+      argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
+      XFA_RESOLVENODE_RS resolveNodeRS;
+      if (ResolveObjects(pThis, hJSObjValue.get(), bsSomExp.AsStringView(),
+                         &resolveNodeRS, bDotAccessor, bHasNoResolveName)) {
+        ParseResolveResult(pThis, resolveNodeRS, hJSObjValue.get(),
+                           &resolveValues[i - 2], &bAttribute);
+        iCounter += resolveValues[i - 2].size();
+      }
+    }
+    if (iCounter < 1) {
+      pContext->ThrowPropertyNotInObjectException(
+          WideString::FromUTF8(bsName.AsStringView()),
+          WideString::FromUTF8(bsSomExp.AsStringView()));
+      return;
+    }
+
+    std::vector<std::unique_ptr<CFXJSE_Value>> values;
+    for (int32_t i = 0; i < iCounter + 2; i++)
+      values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate));
+
+    values[0]->SetInteger(1);
+    if (bAttribute)
+      values[1]->SetString(bsName.AsStringView());
+    else
+      values[1]->SetNull();
+
+    int32_t iIndex = 2;
+    for (int32_t i = 0; i < iLength - 2; i++) {
+      for (size_t j = 0; j < resolveValues[i].size(); j++) {
+        values[iIndex]->Assign(resolveValues[i][j].get());
+        iIndex++;
+      }
+    }
+    args.GetReturnValue()->SetArray(values);
+    return;
+  }
+
+  XFA_RESOLVENODE_RS resolveNodeRS;
+  bool bRet = false;
+  ByteString bsAccessorName = args.GetUTF8String(1);
+  if (argAccessor->IsObject() ||
+      (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
+    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
+                          &resolveNodeRS, bDotAccessor, bHasNoResolveName);
+  } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
+             GetObjectForName(pThis, argAccessor.get(),
+                              bsAccessorName.AsStringView())) {
+    bRet = ResolveObjects(pThis, argAccessor.get(), bsSomExp.AsStringView(),
+                          &resolveNodeRS, bDotAccessor, bHasNoResolveName);
+  }
+  if (!bRet) {
+    pContext->ThrowPropertyNotInObjectException(
+        WideString::FromUTF8(bsName.AsStringView()),
+        WideString::FromUTF8(bsSomExp.AsStringView()));
+    return;
+  }
+
+  std::vector<std::unique_ptr<CFXJSE_Value>> resolveValues;
+  bool bAttribute = false;
+  ParseResolveResult(pThis, resolveNodeRS, argAccessor.get(), &resolveValues,
+                     &bAttribute);
+
+  std::vector<std::unique_ptr<CFXJSE_Value>> values;
+  for (size_t i = 0; i < resolveValues.size() + 2; i++)
+    values.push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate));
+
+  values[0]->SetInteger(1);
+  if (bAttribute)
+    values[1]->SetString(bsName.AsStringView());
+  else
+    values[1]->SetNull();
+
+  for (size_t i = 0; i < resolveValues.size(); i++)
+    values[i + 2]->Assign(resolveValues[i].get());
+
+  args.GetReturnValue()->SetArray(values);
+}
+
 void CFXJSE_FormCalcContext::ThrowNoDefaultPropertyException(
     ByteStringView name) const {
   ThrowException(WideString::FromUTF8(name) +
diff --git a/fxjs/xfa/cfxjse_formcalc_context.h b/fxjs/xfa/cfxjse_formcalc_context.h
index cbf9551..cf1bc95 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.h
+++ b/fxjs/xfa/cfxjse_formcalc_context.h
@@ -389,6 +389,11 @@
   void GlobalPropertyGetter(CFXJSE_Value* pValue);
 
  private:
+  static void DotAccessorCommon(CFXJSE_Value* pThis,
+                                ByteStringView bsFuncName,
+                                CFXJSE_Arguments& args,
+                                bool bDotAccessor);
+
   v8::Isolate* GetScriptRuntime() const { return m_pIsolate.Get(); }
   CXFA_Document* GetDocument() const { return m_pDocument.Get(); }