// Copyright 2017 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 "fxjs/xfa/cjx_object.h"

#include <set>
#include <tuple>

#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_memory.h"
#include "core/fxcrt/xml/cfx_xmlelement.h"
#include "core/fxcrt/xml/cfx_xmltext.h"
#include "fxjs/cjs_result.h"
#include "fxjs/fxv8.h"
#include "fxjs/gc/container_trace.h"
#include "fxjs/xfa/cfxjse_engine.h"
#include "fxjs/xfa/cfxjse_mapmodule.h"
#include "fxjs/xfa/cjx_boolean.h"
#include "fxjs/xfa/cjx_draw.h"
#include "fxjs/xfa/cjx_field.h"
#include "fxjs/xfa/cjx_instancemanager.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
#include "third_party/base/compiler_specific.h"
#include "third_party/base/stl_util.h"
#include "xfa/fgas/crt/cfgas_decimal.h"
#include "xfa/fxfa/cxfa_ffnotify.h"
#include "xfa/fxfa/cxfa_ffwidget.h"
#include "xfa/fxfa/parser/cxfa_border.h"
#include "xfa/fxfa/parser/cxfa_datavalue.h"
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_edge.h"
#include "xfa/fxfa/parser/cxfa_fill.h"
#include "xfa/fxfa/parser/cxfa_font.h"
#include "xfa/fxfa/parser/cxfa_measurement.h"
#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/cxfa_proto.h"
#include "xfa/fxfa/parser/cxfa_subform.h"
#include "xfa/fxfa/parser/cxfa_validate.h"
#include "xfa/fxfa/parser/cxfa_value.h"
#include "xfa/fxfa/parser/xfa_basic_data.h"
#include "xfa/fxfa/parser/xfa_utils.h"

namespace {

enum XFA_KEYTYPE {
  XFA_KEYTYPE_Custom,
  XFA_KEYTYPE_Element,
};

uint32_t GetMapKey_Custom(WideStringView wsKey) {
  uint32_t dwKey = FX_HashCode_GetW(wsKey);
  return ((dwKey << 1) | XFA_KEYTYPE_Custom);
}

uint32_t GetMapKey_Element(XFA_Element eType, XFA_Attribute eAttribute) {
  return ((static_cast<uint32_t>(eType) << 16) |
          (static_cast<uint32_t>(eAttribute) << 8) | XFA_KEYTYPE_Element);
}

std::tuple<int32_t, int32_t, int32_t> StrToRGB(const WideString& strRGB) {
  int32_t r = 0;
  int32_t g = 0;
  int32_t b = 0;

  size_t iIndex = 0;
  for (size_t i = 0; i < strRGB.GetLength(); ++i) {
    wchar_t ch = strRGB[i];
    if (ch == L',')
      ++iIndex;
    if (iIndex > 2)
      break;

    int32_t iValue = ch - L'0';
    if (iValue >= 0 && iValue <= 9) {
      switch (iIndex) {
        case 0:
          r = r * 10 + iValue;
          break;
        case 1:
          g = g * 10 + iValue;
          break;
        default:
          b = b * 10 + iValue;
          break;
      }
    }
  }
  return {r, g, b};
}

}  // namespace

CJX_Object::CJX_Object(CXFA_Object* obj) : object_(obj) {}

CJX_Object::~CJX_Object() = default;

CJX_Object* CJX_Object::AsCJXObject() {
  return this;
}

void CJX_Object::Trace(cppgc::Visitor* visitor) const {
  visitor->Trace(object_);
  visitor->Trace(layout_item_);
  visitor->Trace(calc_data_);
}

bool CJX_Object::DynamicTypeIs(TypeTag eType) const {
  return eType == static_type__;
}

void CJX_Object::DefineMethods(pdfium::span<const CJX_MethodSpec> methods) {
  for (const auto& item : methods)
    method_specs_[item.pName] = item.pMethodCall;
}

CXFA_Document* CJX_Object::GetDocument() const {
  return object_->GetDocument();
}

CXFA_Node* CJX_Object::GetXFANode() const {
  return ToNode(GetXFAObject());
}

void CJX_Object::className(v8::Isolate* pIsolate,
                           v8::Local<v8::Value>* pValue,
                           bool bSetting,
                           XFA_Attribute eAttribute) {
  if (bSetting) {
    ThrowInvalidPropertyException();
    return;
  }
  *pValue = fxv8::NewStringHelper(pIsolate, GetXFAObject()->GetClassName());
}

int32_t CJX_Object::Subform_and_SubformSet_InstanceIndex() {
  int32_t index = 0;
  for (CXFA_Node* pNode = GetXFANode()->GetPrevSibling(); pNode;
       pNode = pNode->GetPrevSibling()) {
    if ((pNode->GetElementType() != XFA_Element::Subform) &&
        (pNode->GetElementType() != XFA_Element::SubformSet)) {
      break;
    }
    index++;
  }
  return index;
}

bool CJX_Object::HasMethod(const WideString& func) const {
  return pdfium::Contains(method_specs_, func.ToUTF8());
}

CJS_Result CJX_Object::RunMethod(
    const WideString& func,
    const std::vector<v8::Local<v8::Value>>& params) {
  auto it = method_specs_.find(func.ToUTF8());
  if (it == method_specs_.end())
    return CJS_Result::Failure(JSMessage::kUnknownMethod);

  return it->second(this, GetXFAObject()->GetDocument()->GetScriptContext(),
                    params);
}

void CJX_Object::ThrowTooManyOccurancesException(const WideString& obj) const {
  ThrowException(WideString::FromASCII("The element [") + obj +
                 WideString::FromASCII(
                     "] has violated its allowable number of occurrences."));
}

void CJX_Object::ThrowInvalidPropertyException() const {
  ThrowException(WideString::FromASCII("Invalid property set operation."));
}

void CJX_Object::ThrowIndexOutOfBoundsException() const {
  ThrowException(WideString::FromASCII("Index value is out of bounds."));
}

void CJX_Object::ThrowParamCountMismatchException(
    const WideString& method) const {
  ThrowException(
      WideString::FromASCII("Incorrect number of parameters calling method '") +
      method + WideString::FromASCII("'."));
}

void CJX_Object::ThrowArgumentMismatchException() const {
  ThrowException(WideString::FromASCII(
      "Argument mismatch in property or function argument."));
}

void CJX_Object::ThrowException(const WideString& str) const {
  DCHECK(!str.IsEmpty());
  FXJSE_ThrowMessage(str.ToUTF8().AsStringView());
}

bool CJX_Object::HasAttribute(XFA_Attribute eAttr) const {
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  return HasMapModuleKey(key);
}

void CJX_Object::SetAttributeByEnum(XFA_Attribute eAttr,
                                    const WideString& wsValue,
                                    bool bNotify) {
  switch (GetXFANode()->GetAttributeType(eAttr)) {
    case XFA_AttributeType::Enum: {
      Optional<XFA_AttributeValue> item =
          XFA_GetAttributeValueByName(wsValue.AsStringView());
      SetEnum(eAttr,
              item.has_value() ? item.value()
                               : GetXFANode()->GetDefaultEnum(eAttr).value(),
              bNotify);
      break;
    }
    case XFA_AttributeType::CData:
      SetCDataImpl(eAttr, WideString(wsValue), bNotify, false);
      break;
    case XFA_AttributeType::Boolean:
      SetBoolean(eAttr, !wsValue.EqualsASCII("0"), bNotify);
      break;
    case XFA_AttributeType::Integer:
      SetInteger(eAttr,
                 FXSYS_roundf(FXSYS_wcstof(wsValue.c_str(), wsValue.GetLength(),
                                           nullptr)),
                 bNotify);
      break;
    case XFA_AttributeType::Measure:
      SetMeasure(eAttr, CXFA_Measurement(wsValue.AsStringView()), bNotify);
      break;
    default:
      break;
  }
}

void CJX_Object::SetAttributeByString(WideStringView wsAttr,
                                      const WideString& wsValue) {
  Optional<XFA_ATTRIBUTEINFO> attr = XFA_GetAttributeByName(wsAttr);
  if (attr.has_value()) {
    SetAttributeByEnum(attr.value().attribute, wsValue, true);
    return;
  }
  uint32_t key = GetMapKey_Custom(wsAttr);
  SetMapModuleString(key, wsValue);
}

WideString CJX_Object::GetAttributeByString(WideStringView attr) const {
  Optional<WideString> result;
  Optional<XFA_ATTRIBUTEINFO> enum_attr = XFA_GetAttributeByName(attr);
  if (enum_attr.has_value())
    result = TryAttribute(enum_attr.value().attribute, true);
  else
    result = GetMapModuleStringFollowingChain(GetMapKey_Custom(attr));
  return result.value_or(WideString());
}

WideString CJX_Object::GetAttributeByEnum(XFA_Attribute attr) const {
  return TryAttribute(attr, true).value_or(WideString());
}

Optional<WideString> CJX_Object::TryAttribute(XFA_Attribute eAttr,
                                              bool bUseDefault) const {
  switch (GetXFANode()->GetAttributeType(eAttr)) {
    case XFA_AttributeType::Enum: {
      Optional<XFA_AttributeValue> value = TryEnum(eAttr, bUseDefault);
      if (!value.has_value())
        return pdfium::nullopt;
      return WideString::FromASCII(XFA_AttributeValueToName(value.value()));
    }
    case XFA_AttributeType::CData:
      return TryCData(eAttr, bUseDefault);

    case XFA_AttributeType::Boolean: {
      Optional<bool> value = TryBoolean(eAttr, bUseDefault);
      if (!value.has_value())
        return pdfium::nullopt;
      return WideString(value.value() ? L"1" : L"0");
    }
    case XFA_AttributeType::Integer: {
      Optional<int32_t> iValue = TryInteger(eAttr, bUseDefault);
      if (!iValue.has_value())
        return pdfium::nullopt;
      return WideString::Format(L"%d", iValue.value());
    }
    case XFA_AttributeType::Measure: {
      Optional<CXFA_Measurement> value = TryMeasure(eAttr, bUseDefault);
      if (!value.has_value())
        return pdfium::nullopt;
      return value->ToString();
    }
    default:
      break;
  }
  return pdfium::nullopt;
}

void CJX_Object::RemoveAttribute(WideStringView wsAttr) {
  RemoveMapModuleKey(GetMapKey_Custom(wsAttr));
}

Optional<bool> CJX_Object::TryBoolean(XFA_Attribute eAttr,
                                      bool bUseDefault) const {
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  Optional<int32_t> value = GetMapModuleValueFollowingChain(key);
  if (value.has_value())
    return !!value.value();
  if (!bUseDefault)
    return pdfium::nullopt;
  return GetXFANode()->GetDefaultBoolean(eAttr);
}

void CJX_Object::SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify) {
  CFX_XMLElement* elem = SetValue(eAttr, static_cast<int32_t>(bValue), bNotify);
  if (elem) {
    elem->SetAttribute(WideString::FromASCII(XFA_AttributeToName(eAttr)),
                       bValue ? L"1" : L"0");
  }
}

bool CJX_Object::GetBoolean(XFA_Attribute eAttr) const {
  return TryBoolean(eAttr, true).value_or(false);
}

void CJX_Object::SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify) {
  CFX_XMLElement* elem = SetValue(eAttr, iValue, bNotify);
  if (elem) {
    elem->SetAttribute(WideString::FromASCII(XFA_AttributeToName(eAttr)),
                       WideString::Format(L"%d", iValue));
  }
}

int32_t CJX_Object::GetInteger(XFA_Attribute eAttr) const {
  return TryInteger(eAttr, true).value_or(0);
}

Optional<int32_t> CJX_Object::TryInteger(XFA_Attribute eAttr,
                                         bool bUseDefault) const {
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  Optional<int32_t> value = GetMapModuleValueFollowingChain(key);
  if (value.has_value())
    return value.value();
  if (!bUseDefault)
    return pdfium::nullopt;
  return GetXFANode()->GetDefaultInteger(eAttr);
}

Optional<XFA_AttributeValue> CJX_Object::TryEnum(XFA_Attribute eAttr,
                                                 bool bUseDefault) const {
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  Optional<int32_t> value = GetMapModuleValueFollowingChain(key);
  if (value.has_value())
    return static_cast<XFA_AttributeValue>(value.value());
  if (!bUseDefault)
    return pdfium::nullopt;
  return GetXFANode()->GetDefaultEnum(eAttr);
}

void CJX_Object::SetEnum(XFA_Attribute eAttr,
                         XFA_AttributeValue eValue,
                         bool bNotify) {
  CFX_XMLElement* elem = SetValue(eAttr, static_cast<int32_t>(eValue), bNotify);
  if (elem) {
    elem->SetAttribute(WideString::FromASCII(XFA_AttributeToName(eAttr)),
                       WideString::FromASCII(XFA_AttributeValueToName(eValue)));
  }
}

XFA_AttributeValue CJX_Object::GetEnum(XFA_Attribute eAttr) const {
  return TryEnum(eAttr, true).value_or(XFA_AttributeValue::Unknown);
}

void CJX_Object::SetMeasure(XFA_Attribute eAttr,
                            const CXFA_Measurement& mValue,
                            bool bNotify) {
  // Can't short-circuit update here when the value is the same since it
  // might have come from further up the chain from where we are setting it.
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  if (bNotify)
    OnChanging(eAttr);
  SetMapModuleMeasurement(key, mValue);
  if (bNotify)
    OnChanged(eAttr, false);
}

Optional<CXFA_Measurement> CJX_Object::TryMeasure(XFA_Attribute eAttr,
                                                  bool bUseDefault) const {
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  Optional<CXFA_Measurement> result =
      GetMapModuleMeasurementFollowingChain(key);
  if (result.has_value())
    return result.value();
  if (!bUseDefault)
    return pdfium::nullopt;
  return GetXFANode()->GetDefaultMeasurement(eAttr);
}

Optional<float> CJX_Object::TryMeasureAsFloat(XFA_Attribute attr) const {
  Optional<CXFA_Measurement> measure = TryMeasure(attr, false);
  if (!measure.has_value())
    return pdfium::nullopt;
  return measure->ToUnit(XFA_Unit::Pt);
}

CXFA_Measurement CJX_Object::GetMeasure(XFA_Attribute eAttr) const {
  return TryMeasure(eAttr, true).value_or(CXFA_Measurement());
}

float CJX_Object::GetMeasureInUnit(XFA_Attribute eAttr, XFA_Unit unit) const {
  return GetMeasure(eAttr).ToUnit(unit);
}

WideString CJX_Object::GetCData(XFA_Attribute eAttr) const {
  return TryCData(eAttr, true).value_or(WideString());
}

void CJX_Object::SetCData(XFA_Attribute eAttr, const WideString& wsValue) {
  return SetCDataImpl(eAttr, wsValue, false, false);
}

void CJX_Object::SetCDataImpl(XFA_Attribute eAttr,
                              const WideString& wsValue,
                              bool bNotify,
                              bool bScriptModify) {
  CXFA_Node* xfaObj = GetXFANode();
  uint32_t key = GetMapKey_Element(xfaObj->GetElementType(), eAttr);
  Optional<WideString> old_value = GetMapModuleString(key);
  if (!old_value.has_value() || old_value.value() != wsValue) {
    if (bNotify)
      OnChanging(eAttr);
    SetMapModuleString(key, wsValue);
    if (eAttr == XFA_Attribute::Name)
      xfaObj->UpdateNameHash();
    if (bNotify)
      OnChanged(eAttr, bScriptModify);
  }

  if (!xfaObj->IsNeedSavingXMLNode() || eAttr == XFA_Attribute::QualifiedName ||
      eAttr == XFA_Attribute::BindingNode) {
    return;
  }

  if (eAttr == XFA_Attribute::Name &&
      (xfaObj->GetElementType() == XFA_Element::DataValue ||
       xfaObj->GetElementType() == XFA_Element::DataGroup)) {
    return;
  }

  if (eAttr == XFA_Attribute::Value) {
    xfaObj->SetToXML(wsValue);
    return;
  }

  WideString wsAttrName = WideString::FromASCII(XFA_AttributeToName(eAttr));
  if (eAttr == XFA_Attribute::ContentType)
    wsAttrName = L"xfa:" + wsAttrName;

  CFX_XMLElement* elem = ToXMLElement(xfaObj->GetXMLMappingNode());
  elem->SetAttribute(wsAttrName, wsValue);
  return;
}

void CJX_Object::SetAttributeValue(const WideString& wsValue,
                                   const WideString& wsXMLValue) {
  SetAttributeValueImpl(wsValue, wsXMLValue, false, false);
}

void CJX_Object::SetAttributeValueImpl(const WideString& wsValue,
                                       const WideString& wsXMLValue,
                                       bool bNotify,
                                       bool bScriptModify) {
  auto* xfaObj = GetXFANode();
  uint32_t key =
      GetMapKey_Element(xfaObj->GetElementType(), XFA_Attribute::Value);
  Optional<WideString> old_value = GetMapModuleString(key);
  if (!old_value.has_value() || old_value.value() != wsValue) {
    if (bNotify)
      OnChanging(XFA_Attribute::Value);
    SetMapModuleString(key, wsValue);
    if (bNotify)
      OnChanged(XFA_Attribute::Value, bScriptModify);
    if (xfaObj->IsNeedSavingXMLNode())
      xfaObj->SetToXML(wsXMLValue);
  }
}

Optional<WideString> CJX_Object::TryCData(XFA_Attribute eAttr,
                                          bool bUseDefault) const {
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  Optional<WideString> value = GetMapModuleStringFollowingChain(key);
  if (value.has_value())
    return value;

  if (!bUseDefault)
    return pdfium::nullopt;

  return GetXFANode()->GetDefaultCData(eAttr);
}

CFX_XMLElement* CJX_Object::SetValue(XFA_Attribute eAttr,
                                     int32_t value,
                                     bool bNotify) {
  uint32_t key = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
  Optional<int32_t> old_value = GetMapModuleValue(key);
  if (!old_value.has_value() || old_value.value() != value) {
    if (bNotify)
      OnChanging(eAttr);
    SetMapModuleValue(key, value);
    if (bNotify)
      OnChanged(eAttr, false);
  }
  CXFA_Node* pNode = GetXFANode();
  return pNode->IsNeedSavingXMLNode() ? ToXMLElement(pNode->GetXMLMappingNode())
                                      : nullptr;
}

void CJX_Object::SetContent(const WideString& wsContent,
                            const WideString& wsXMLValue,
                            bool bNotify,
                            bool bScriptModify,
                            bool bSyncData) {
  CXFA_Node* pNode = nullptr;
  CXFA_Node* pBindNode = nullptr;
  switch (GetXFANode()->GetObjectType()) {
    case XFA_ObjectType::ContainerNode: {
      if (XFA_FieldIsMultiListBox(GetXFANode())) {
        CXFA_Value* pValue =
            GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value);
        if (!pValue)
          break;

        CXFA_Node* pChildValue = pValue->GetFirstChild();
        pChildValue->JSObject()->SetCData(XFA_Attribute::ContentType,
                                          L"text/xml");
        pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
                                            bScriptModify, false);

        CXFA_Node* pBind = GetXFANode()->GetBindData();
        if (bSyncData && pBind) {
          std::vector<WideString> wsSaveTextArray =
              fxcrt::Split(wsContent, L'\n');
          std::vector<CXFA_Node*> valueNodes =
              pBind->GetNodeListForType(XFA_Element::DataValue);

          // Adusting node count might have side effects, do not trust that
          // we'll ever actually get there.
          size_t tries = 0;
          while (valueNodes.size() != wsSaveTextArray.size()) {
            if (++tries > 4)
              return;
            if (valueNodes.size() < wsSaveTextArray.size()) {
              size_t iAddNodes = wsSaveTextArray.size() - valueNodes.size();
              while (iAddNodes-- > 0) {
                CXFA_Node* pValueNodes =
                    pBind->CreateSamePacketNode(XFA_Element::DataValue);
                pValueNodes->JSObject()->SetCData(XFA_Attribute::Name,
                                                  L"value");
                pValueNodes->CreateXMLMappingNode();
                pBind->InsertChildAndNotify(pValueNodes, nullptr);
              }
            } else {
              size_t iDelNodes = valueNodes.size() - wsSaveTextArray.size();
              for (size_t i = 0; i < iDelNodes; ++i)
                pBind->RemoveChildAndNotify(valueNodes[i], true);
            }
            valueNodes = pBind->GetNodeListForType(XFA_Element::DataValue);
          }
          DCHECK_EQ(valueNodes.size(), wsSaveTextArray.size());
          size_t i = 0;
          for (CXFA_Node* pValueNode : valueNodes) {
            pValueNode->JSObject()->SetAttributeValue(wsSaveTextArray[i],
                                                      wsSaveTextArray[i]);
            i++;
          }
          for (auto* pArrayNode : pBind->GetBindItemsCopy()) {
            if (pArrayNode != GetXFANode()) {
              pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
                                                 bScriptModify, false);
            }
          }
        }
        break;
      }
      if (GetXFANode()->GetElementType() == XFA_Element::ExclGroup) {
        pNode = GetXFANode();
      } else {
        CXFA_Value* pValue =
            GetOrCreateProperty<CXFA_Value>(0, XFA_Element::Value);
        if (!pValue)
          break;

        CXFA_Node* pChildValue = pValue->GetFirstChild();
        DCHECK(pChildValue);
        pChildValue->JSObject()->SetContent(wsContent, wsContent, bNotify,
                                            bScriptModify, false);
      }
      pBindNode = GetXFANode()->GetBindData();
      if (pBindNode && bSyncData) {
        pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
                                          bScriptModify, false);
        for (auto* pArrayNode : pBindNode->GetBindItemsCopy()) {
          if (pArrayNode != GetXFANode()) {
            pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
                                               true, false);
          }
        }
      }
      pBindNode = nullptr;
      break;
    }
    case XFA_ObjectType::ContentNode: {
      WideString wsContentType;
      if (GetXFANode()->GetElementType() == XFA_Element::ExData) {
        Optional<WideString> ret =
            TryAttribute(XFA_Attribute::ContentType, false);
        if (ret.has_value())
          wsContentType = ret.value();
        if (wsContentType.EqualsASCII("text/html")) {
          wsContentType.clear();
          SetAttributeByEnum(XFA_Attribute::ContentType, wsContentType, false);
        }
      }

      CXFA_Node* pContentRawDataNode = GetXFANode()->GetFirstChild();
      if (!pContentRawDataNode) {
        pContentRawDataNode = GetXFANode()->CreateSamePacketNode(
            wsContentType.EqualsASCII("text/xml") ? XFA_Element::Sharpxml
                                                  : XFA_Element::Sharptext);
        GetXFANode()->InsertChildAndNotify(pContentRawDataNode, nullptr);
      }
      pContentRawDataNode->JSObject()->SetContent(
          wsContent, wsXMLValue, bNotify, bScriptModify, bSyncData);
      return;
    }
    case XFA_ObjectType::NodeC:
    case XFA_ObjectType::TextNode:
      pNode = GetXFANode();
      break;
    case XFA_ObjectType::NodeV:
      pNode = GetXFANode();
      if (bSyncData && GetXFANode()->GetPacketType() == XFA_PacketType::Form) {
        CXFA_Node* pParent = GetXFANode()->GetParent();
        if (pParent) {
          pParent = pParent->GetParent();
        }
        if (pParent && pParent->GetElementType() == XFA_Element::Value) {
          pParent = pParent->GetParent();
          if (pParent && pParent->IsContainerNode()) {
            pBindNode = pParent->GetBindData();
            if (pBindNode) {
              pBindNode->JSObject()->SetContent(wsContent, wsXMLValue, bNotify,
                                                bScriptModify, false);
            }
          }
        }
      }
      break;
    default:
      if (GetXFANode()->GetElementType() == XFA_Element::DataValue) {
        pNode = GetXFANode();
        pBindNode = GetXFANode();
      }
      break;
  }
  if (!pNode)
    return;

  SetAttributeValueImpl(wsContent, wsXMLValue, bNotify, bScriptModify);
  if (pBindNode && bSyncData) {
    for (auto* pArrayNode : pBindNode->GetBindItemsCopy()) {
      pArrayNode->JSObject()->SetContent(wsContent, wsContent, bNotify,
                                         bScriptModify, false);
    }
  }
}

WideString CJX_Object::GetContent(bool bScriptModify) const {
  return TryContent(bScriptModify, true).value_or(WideString());
}

Optional<WideString> CJX_Object::TryContent(bool bScriptModify,
                                            bool bProto) const {
  CXFA_Node* pNode = nullptr;
  switch (GetXFANode()->GetObjectType()) {
    case XFA_ObjectType::ContainerNode:
      if (GetXFANode()->GetElementType() == XFA_Element::ExclGroup) {
        pNode = GetXFANode();
      } else {
        CXFA_Value* pValue =
            GetXFANode()->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
        if (!pValue)
          return pdfium::nullopt;

        CXFA_Node* pChildValue = pValue->GetFirstChild();
        if (pChildValue && XFA_FieldIsMultiListBox(GetXFANode())) {
          pChildValue->JSObject()->SetAttributeByEnum(
              XFA_Attribute::ContentType, L"text/xml", false);
        }
        if (!pChildValue)
          return pdfium::nullopt;
        return pChildValue->JSObject()->TryContent(bScriptModify, bProto);
      }
      break;
    case XFA_ObjectType::ContentNode: {
      CXFA_Node* pContentRawDataNode = GetXFANode()->GetFirstChild();
      if (!pContentRawDataNode) {
        XFA_Element element = XFA_Element::Sharptext;
        if (GetXFANode()->GetElementType() == XFA_Element::ExData) {
          Optional<WideString> contentType =
              TryAttribute(XFA_Attribute::ContentType, false);
          if (contentType.has_value()) {
            if (contentType.value().EqualsASCII("text/html"))
              element = XFA_Element::SharpxHTML;
            else if (contentType.value().EqualsASCII("text/xml"))
              element = XFA_Element::Sharpxml;
          }
        }
        pContentRawDataNode = GetXFANode()->CreateSamePacketNode(element);
        GetXFANode()->InsertChildAndNotify(pContentRawDataNode, nullptr);
      }
      return pContentRawDataNode->JSObject()->TryContent(bScriptModify, true);
    }
    case XFA_ObjectType::NodeC:
    case XFA_ObjectType::NodeV:
    case XFA_ObjectType::TextNode:
      pNode = GetXFANode();
      FALLTHROUGH;
    default:
      if (GetXFANode()->GetElementType() == XFA_Element::DataValue)
        pNode = GetXFANode();
      break;
  }
  if (pNode) {
    if (bScriptModify) {
      CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
      pScriptContext->AddNodesOfRunScript(GetXFANode());
    }
    return TryCData(XFA_Attribute::Value, false);
  }
  return pdfium::nullopt;
}

Optional<WideString> CJX_Object::TryNamespace() const {
  if (GetXFANode()->IsModelNode() ||
      GetXFANode()->GetElementType() == XFA_Element::Packet) {
    CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
    CFX_XMLElement* element = ToXMLElement(pXMLNode);
    if (!element)
      return pdfium::nullopt;

    return element->GetNamespaceURI();
  }

  if (GetXFANode()->GetPacketType() != XFA_PacketType::Datasets)
    return GetXFANode()->GetModelNode()->JSObject()->TryNamespace();

  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
  CFX_XMLElement* element = ToXMLElement(pXMLNode);
  if (!element)
    return pdfium::nullopt;

  if (GetXFANode()->GetElementType() == XFA_Element::DataValue &&
      GetEnum(XFA_Attribute::Contains) == XFA_AttributeValue::MetaData) {
    WideString wsNamespace;
    if (!XFA_FDEExtension_ResolveNamespaceQualifier(
            element, GetCData(XFA_Attribute::QualifiedName), &wsNamespace)) {
      return pdfium::nullopt;
    }
    return wsNamespace;
  }
  return element->GetNamespaceURI();
}

std::pair<CXFA_Node*, int32_t> CJX_Object::GetPropertyInternal(
    int32_t index,
    XFA_Element eProperty) const {
  return GetXFANode()->GetProperty(index, eProperty);
}

CXFA_Node* CJX_Object::GetOrCreatePropertyInternal(int32_t index,
                                                   XFA_Element eProperty) {
  return GetXFANode()->GetOrCreateProperty(index, eProperty);
}

CFXJSE_MapModule* CJX_Object::CreateMapModule() {
  if (!map_module_)
    map_module_ = std::make_unique<CFXJSE_MapModule>();
  return map_module_.get();
}

CFXJSE_MapModule* CJX_Object::GetMapModule() const {
  return map_module_.get();
}

void CJX_Object::SetMapModuleValue(uint32_t key, int32_t value) {
  CreateMapModule()->SetValue(key, value);
}

void CJX_Object::SetMapModuleString(uint32_t key, const WideString& wsValue) {
  CreateMapModule()->SetString(key, wsValue);
}

void CJX_Object::SetMapModuleMeasurement(uint32_t key,
                                         const CXFA_Measurement& value) {
  CreateMapModule()->SetMeasurement(key, value);
}

Optional<int32_t> CJX_Object::GetMapModuleValue(uint32_t key) const {
  CFXJSE_MapModule* pModule = GetMapModule();
  if (!pModule)
    return pdfium::nullopt;
  return pModule->GetValue(key);
}

Optional<WideString> CJX_Object::GetMapModuleString(uint32_t key) const {
  CFXJSE_MapModule* pModule = GetMapModule();
  if (!pModule)
    return pdfium::nullopt;
  return pModule->GetString(key);
}

Optional<CXFA_Measurement> CJX_Object::GetMapModuleMeasurement(
    uint32_t key) const {
  CFXJSE_MapModule* pModule = GetMapModule();
  if (!pModule)
    return pdfium::nullopt;
  return pModule->GetMeasurement(key);
}

Optional<int32_t> CJX_Object::GetMapModuleValueFollowingChain(
    uint32_t key) const {
  std::set<const CXFA_Node*> visited;
  for (const CXFA_Node* pNode = GetXFANode(); pNode;
       pNode = pNode->GetTemplateNodeIfExists()) {
    if (!visited.insert(pNode).second)
      break;

    Optional<int32_t> result = pNode->JSObject()->GetMapModuleValue(key);
    if (result.has_value())
      return result;

    if (pNode->GetPacketType() == XFA_PacketType::Datasets)
      break;
  }
  return pdfium::nullopt;
}

Optional<WideString> CJX_Object::GetMapModuleStringFollowingChain(
    uint32_t key) const {
  std::set<const CXFA_Node*> visited;
  for (const CXFA_Node* pNode = GetXFANode(); pNode;
       pNode = pNode->GetTemplateNodeIfExists()) {
    if (!visited.insert(pNode).second)
      break;

    Optional<WideString> result = pNode->JSObject()->GetMapModuleString(key);
    if (result.has_value())
      return result;

    if (pNode->GetPacketType() == XFA_PacketType::Datasets)
      break;
  }
  return pdfium::nullopt;
}

Optional<CXFA_Measurement> CJX_Object::GetMapModuleMeasurementFollowingChain(
    uint32_t key) const {
  std::set<const CXFA_Node*> visited;
  for (const CXFA_Node* pNode = GetXFANode(); pNode;
       pNode = pNode->GetTemplateNodeIfExists()) {
    if (!visited.insert(pNode).second)
      break;

    Optional<CXFA_Measurement> result =
        pNode->JSObject()->GetMapModuleMeasurement(key);
    if (result.has_value())
      return result;

    if (pNode->GetPacketType() == XFA_PacketType::Datasets)
      break;
  }
  return pdfium::nullopt;
}

bool CJX_Object::HasMapModuleKey(uint32_t key) const {
  CFXJSE_MapModule* pModule = GetMapModule();
  return pModule && pModule->HasKey(key);
}

void CJX_Object::RemoveMapModuleKey(uint32_t key) {
  CFXJSE_MapModule* pModule = GetMapModule();
  if (pModule)
    pModule->RemoveKey(key);
}

void CJX_Object::MergeAllData(CXFA_Object* pDstObj) {
  CFXJSE_MapModule* pDstModule = ToNode(pDstObj)->JSObject()->CreateMapModule();
  CFXJSE_MapModule* pSrcModule = GetMapModule();
  if (!pSrcModule)
    return;

  pDstModule->MergeDataFrom(pSrcModule);
}

void CJX_Object::MoveBufferMapData(CXFA_Object* pDstObj) {
  if (!pDstObj)
    return;

  if (pDstObj->GetElementType() == GetXFAObject()->GetElementType())
    ToNode(pDstObj)->JSObject()->TakeCalcDataFrom(this);

  if (!pDstObj->IsNodeV())
    return;

  WideString wsValue = ToNode(pDstObj)->JSObject()->GetContent(false);
  WideString wsFormatValue(wsValue);
  CXFA_Node* pNode = ToNode(pDstObj)->GetContainerNode();
  if (pNode)
    wsFormatValue = pNode->GetFormatDataValue(wsValue);

  ToNode(pDstObj)->JSObject()->SetContent(wsValue, wsFormatValue, true, true,
                                          true);
}

void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcObj, CXFA_Object* pDstObj) {
  if (!pSrcObj || !pDstObj)
    return;

  CXFA_Node* pSrcChild = ToNode(pSrcObj)->GetFirstChild();
  CXFA_Node* pDstChild = ToNode(pDstObj)->GetFirstChild();
  while (pSrcChild && pDstChild) {
    MoveBufferMapData(pSrcChild, pDstChild);
    pSrcChild = pSrcChild->GetNextSibling();
    pDstChild = pDstChild->GetNextSibling();
  }
  ToNode(pSrcObj)->JSObject()->MoveBufferMapData(pDstObj);
}

void CJX_Object::OnChanging(XFA_Attribute eAttr) {
  if (!GetXFANode()->IsInitialized())
    return;

  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
  if (!pNotify)
    return;

  pNotify->OnValueChanging(GetXFANode(), eAttr);
}

void CJX_Object::OnChanged(XFA_Attribute eAttr, bool bScriptModify) {
  if (!GetXFANode()->IsInitialized())
    return;

  GetXFANode()->SendAttributeChangeMessage(eAttr, bScriptModify);
}

CJX_Object::CalcData* CJX_Object::GetOrCreateCalcData(cppgc::Heap* heap) {
  if (!calc_data_) {
    calc_data_ =
        cppgc::MakeGarbageCollected<CalcData>(heap->GetAllocationHandle());
  }
  return calc_data_;
}

void CJX_Object::TakeCalcDataFrom(CJX_Object* that) {
  calc_data_ = that->calc_data_;
  that->calc_data_ = nullptr;
}

void CJX_Object::ScriptAttributeString(v8::Isolate* pIsolate,
                                       v8::Local<v8::Value>* pValue,
                                       bool bSetting,
                                       XFA_Attribute eAttribute) {
  if (!bSetting) {
    *pValue = fxv8::NewStringHelper(
        pIsolate, GetAttributeByEnum(eAttribute).ToUTF8().AsStringView());
    return;
  }

  WideString wsValue = fxv8::ReentrantToWideStringHelper(pIsolate, *pValue);
  SetAttributeByEnum(eAttribute, wsValue, true);
  if (eAttribute != XFA_Attribute::Use ||
      GetXFAObject()->GetElementType() != XFA_Element::Desc) {
    return;
  }

  CXFA_Node* pTemplateNode =
      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Template));
  CXFA_Subform* pSubForm =
      pTemplateNode->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
  CXFA_Proto* pProtoRoot =
      pSubForm ? pSubForm->GetFirstChildByClass<CXFA_Proto>(XFA_Element::Proto)
               : nullptr;

  WideString wsID;
  WideString wsSOM;
  if (!wsValue.IsEmpty()) {
    if (wsValue[0] == '#')
      wsID = wsValue.Substr(1, wsValue.GetLength() - 1);
    else
      wsSOM = std::move(wsValue);
  }

  CXFA_Node* pProtoNode = nullptr;
  if (!wsSOM.IsEmpty()) {
    constexpr XFA_ResolveNodeMask kFlags =
        XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
        XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
        XFA_RESOLVENODE_Siblings;
    Optional<CFXJSE_Engine::ResolveResult> maybeResult =
        GetDocument()->GetScriptContext()->ResolveObjects(
            pProtoRoot, wsSOM.AsStringView(), kFlags);
    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());
  }
  if (!pProtoNode)
    return;

  CXFA_Node* pHeadChild = GetXFANode()->GetFirstChild();
  while (pHeadChild) {
    CXFA_Node* pSibling = pHeadChild->GetNextSibling();
    GetXFANode()->RemoveChildAndNotify(pHeadChild, true);
    pHeadChild = pSibling;
  }

  CXFA_Node* pProtoForm = pProtoNode->CloneTemplateToForm(true);
  pHeadChild = pProtoForm->GetFirstChild();
  while (pHeadChild) {
    CXFA_Node* pSibling = pHeadChild->GetNextSibling();
    pProtoForm->RemoveChildAndNotify(pHeadChild, true);
    GetXFANode()->InsertChildAndNotify(pHeadChild, nullptr);
    pHeadChild = pSibling;
  }
}

void CJX_Object::ScriptAttributeBool(v8::Isolate* pIsolate,
                                     v8::Local<v8::Value>* pValue,
                                     bool bSetting,
                                     XFA_Attribute eAttribute) {
  if (bSetting) {
    SetBoolean(eAttribute, fxv8::ReentrantToBooleanHelper(pIsolate, *pValue),
               true);
    return;
  }
  *pValue = fxv8::NewStringHelper(pIsolate, GetBoolean(eAttribute) ? "1" : "0");
}

void CJX_Object::ScriptAttributeInteger(v8::Isolate* pIsolate,
                                        v8::Local<v8::Value>* pValue,
                                        bool bSetting,
                                        XFA_Attribute eAttribute) {
  if (bSetting) {
    SetInteger(eAttribute, fxv8::ReentrantToInt32Helper(pIsolate, *pValue),
               true);
    return;
  }
  *pValue = fxv8::NewNumberHelper(pIsolate, GetInteger(eAttribute));
}

void CJX_Object::ScriptSomFontColor(v8::Isolate* pIsolate,
                                    v8::Local<v8::Value>* pValue,
                                    bool bSetting,
                                    XFA_Attribute eAttribute) {
  CXFA_Font* font = ToNode(object_.Get())->GetOrCreateFontIfPossible();
  if (!font)
    return;

  if (bSetting) {
    int32_t r;
    int32_t g;
    int32_t b;
    std::tie(r, g, b) =
        StrToRGB(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
    FX_ARGB color = ArgbEncode(0xff, r, g, b);
    font->SetColor(color);
    return;
  }

  int32_t a;
  int32_t r;
  int32_t g;
  int32_t b;
  std::tie(a, r, g, b) = ArgbDecode(font->GetColor());
  *pValue = fxv8::NewStringHelper(
      pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
}

void CJX_Object::ScriptSomFillColor(v8::Isolate* pIsolate,
                                    v8::Local<v8::Value>* pValue,
                                    bool bSetting,
                                    XFA_Attribute eAttribute) {
  CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
  CXFA_Fill* borderfill = border->GetOrCreateFillIfPossible();
  if (!borderfill)
    return;

  if (bSetting) {
    int32_t r;
    int32_t g;
    int32_t b;
    std::tie(r, g, b) =
        StrToRGB(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
    FX_ARGB color = ArgbEncode(0xff, r, g, b);
    borderfill->SetColor(color);
    return;
  }

  FX_ARGB color = borderfill->GetColor(false);
  int32_t a;
  int32_t r;
  int32_t g;
  int32_t b;
  std::tie(a, r, g, b) = ArgbDecode(color);
  *pValue = fxv8::NewStringHelper(
      pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
}

void CJX_Object::ScriptSomBorderColor(v8::Isolate* pIsolate,
                                      v8::Local<v8::Value>* pValue,
                                      bool bSetting,
                                      XFA_Attribute eAttribute) {
  CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
  int32_t iSize = border->CountEdges();
  if (bSetting) {
    int32_t r = 0;
    int32_t g = 0;
    int32_t b = 0;
    std::tie(r, g, b) =
        StrToRGB(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
    FX_ARGB rgb = ArgbEncode(100, r, g, b);
    for (int32_t i = 0; i < iSize; ++i) {
      CXFA_Edge* edge = border->GetEdgeIfExists(i);
      if (edge)
        edge->SetColor(rgb);
    }

    return;
  }

  CXFA_Edge* edge = border->GetEdgeIfExists(0);
  FX_ARGB color = edge ? edge->GetColor() : CXFA_Edge::kDefaultColor;
  int32_t a;
  int32_t r;
  int32_t g;
  int32_t b;
  std::tie(a, r, g, b) = ArgbDecode(color);
  *pValue = fxv8::NewStringHelper(
      pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
}

void CJX_Object::ScriptSomBorderWidth(v8::Isolate* pIsolate,
                                      v8::Local<v8::Value>* pValue,
                                      bool bSetting,
                                      XFA_Attribute eAttribute) {
  CXFA_Border* border = ToNode(object_.Get())->GetOrCreateBorderIfPossible();
  if (bSetting) {
    CXFA_Edge* edge = border->GetEdgeIfExists(0);
    CXFA_Measurement thickness =
        edge ? edge->GetMSThickness() : CXFA_Measurement(0.5, XFA_Unit::Pt);
    *pValue = fxv8::NewStringHelper(
        pIsolate, thickness.ToString().ToUTF8().AsStringView());
    return;
  }

  if (pValue->IsEmpty())
    return;

  WideString wsThickness = fxv8::ReentrantToWideStringHelper(pIsolate, *pValue);
  for (int32_t i = 0; i < border->CountEdges(); ++i) {
    CXFA_Edge* edge = border->GetEdgeIfExists(i);
    if (edge)
      edge->SetMSThickness(CXFA_Measurement(wsThickness.AsStringView()));
  }
}

void CJX_Object::ScriptSomMessage(v8::Isolate* pIsolate,
                                  v8::Local<v8::Value>* pValue,
                                  bool bSetting,
                                  XFA_SOM_MESSAGETYPE iMessageType) {
  bool bNew = false;
  CXFA_Validate* validate = ToNode(object_.Get())->GetValidateIfExists();
  if (!validate) {
    validate = ToNode(object_.Get())->GetOrCreateValidateIfPossible();
    bNew = true;
  }

  if (bSetting) {
    if (validate) {
      switch (iMessageType) {
        case XFA_SOM_ValidationMessage:
          validate->SetScriptMessageText(
              fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
          break;
        case XFA_SOM_FormatMessage:
          validate->SetFormatMessageText(
              fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
          break;
        case XFA_SOM_MandatoryMessage:
          validate->SetNullMessageText(
              fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
          break;
        default:
          break;
      }
    }

    if (!bNew) {
      CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
      if (!pNotify)
        return;

      pNotify->AddCalcValidate(GetXFANode());
    }
    return;
  }

  if (!validate) {
    // TODO(dsinclair): Better error message?
    ThrowInvalidPropertyException();
    return;
  }

  WideString wsMessage;
  switch (iMessageType) {
    case XFA_SOM_ValidationMessage:
      wsMessage = validate->GetScriptMessageText();
      break;
    case XFA_SOM_FormatMessage:
      wsMessage = validate->GetFormatMessageText();
      break;
    case XFA_SOM_MandatoryMessage:
      wsMessage = validate->GetNullMessageText();
      break;
    default:
      break;
  }
  *pValue = fxv8::NewStringHelper(pIsolate, wsMessage.ToUTF8().AsStringView());
}

void CJX_Object::ScriptSomValidationMessage(v8::Isolate* pIsolate,
                                            v8::Local<v8::Value>* pValue,
                                            bool bSetting,
                                            XFA_Attribute eAttribute) {
  ScriptSomMessage(pIsolate, pValue, bSetting, XFA_SOM_ValidationMessage);
}

void CJX_Object::ScriptSomMandatoryMessage(v8::Isolate* pIsolate,
                                           v8::Local<v8::Value>* pValue,
                                           bool bSetting,
                                           XFA_Attribute eAttribute) {
  ScriptSomMessage(pIsolate, pValue, bSetting, XFA_SOM_MandatoryMessage);
}

void CJX_Object::ScriptSomDefaultValue(v8::Isolate* pIsolate,
                                       v8::Local<v8::Value>* pValue,
                                       bool bSetting,
                                       XFA_Attribute /* unused */) {
  XFA_Element eType = GetXFANode()->GetElementType();

  // TODO(dsinclair): This should look through the properties on the node to see
  // if defaultValue is defined and, if so, call that one. Just have to make
  // sure that those defaultValue calls don't call back to this one ....
  if (eType == XFA_Element::Field) {
    static_cast<CJX_Field*>(this)->defaultValue(pIsolate, pValue, bSetting,
                                                XFA_Attribute::Unknown);
    return;
  }
  if (eType == XFA_Element::Draw) {
    static_cast<CJX_Draw*>(this)->defaultValue(pIsolate, pValue, bSetting,
                                               XFA_Attribute::Unknown);
    return;
  }
  if (eType == XFA_Element::Boolean) {
    static_cast<CJX_Boolean*>(this)->defaultValue(pIsolate, pValue, bSetting,
                                                  XFA_Attribute::Unknown);
    return;
  }

  if (bSetting) {
    WideString wsNewValue;
    if (pValue && !(pValue->IsEmpty() || fxv8::IsNull(*pValue) ||
                    fxv8::IsUndefined(*pValue))) {
      wsNewValue = fxv8::ReentrantToWideStringHelper(pIsolate, *pValue);
    }

    WideString wsFormatValue = wsNewValue;
    CXFA_Node* pContainerNode = nullptr;
    if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) {
      WideString wsPicture;
      for (auto* pFormNode : GetXFANode()->GetBindItemsCopy()) {
        if (!pFormNode || pFormNode->HasRemovedChildren())
          continue;

        pContainerNode = pFormNode->GetContainerNode();
        if (pContainerNode) {
          wsPicture =
              pContainerNode->GetPictureContent(XFA_ValuePicture::kDataBind);
        }
        if (!wsPicture.IsEmpty())
          break;

        pContainerNode = nullptr;
      }
    } else if (GetXFANode()->GetPacketType() == XFA_PacketType::Form) {
      pContainerNode = GetXFANode()->GetContainerNode();
    }

    if (pContainerNode)
      wsFormatValue = pContainerNode->GetFormatDataValue(wsNewValue);

    SetContent(wsNewValue, wsFormatValue, true, true, true);
    return;
  }

  WideString content = GetContent(true);
  if (content.IsEmpty() && eType != XFA_Element::Text &&
      eType != XFA_Element::SubmitUrl) {
    *pValue = fxv8::NewNullHelper(pIsolate);
  } else if (eType == XFA_Element::Integer) {
    *pValue = fxv8::NewNumberHelper(pIsolate, FXSYS_wtoi(content.c_str()));
  } else if (eType == XFA_Element::Float || eType == XFA_Element::Decimal) {
    CFGAS_Decimal decimal(content.AsStringView());
    *pValue = fxv8::NewNumberHelper(pIsolate, decimal.ToFloat());
  } else {
    *pValue = fxv8::NewStringHelper(pIsolate, content.ToUTF8().AsStringView());
  }
}

void CJX_Object::ScriptSomDefaultValue_Read(v8::Isolate* pIsolate,
                                            v8::Local<v8::Value>* pValue,
                                            bool bSetting,
                                            XFA_Attribute eAttribute) {
  if (bSetting) {
    ThrowInvalidPropertyException();
    return;
  }

  WideString content = GetContent(true);
  if (content.IsEmpty()) {
    *pValue = fxv8::NewNullHelper(pIsolate);
    return;
  }
  *pValue = fxv8::NewStringHelper(pIsolate, content.ToUTF8().AsStringView());
}

void CJX_Object::ScriptSomDataNode(v8::Isolate* pIsolate,
                                   v8::Local<v8::Value>* pValue,
                                   bool bSetting,
                                   XFA_Attribute eAttribute) {
  if (bSetting) {
    ThrowInvalidPropertyException();
    return;
  }

  CXFA_Node* pDataNode = GetXFANode()->GetBindData();
  if (!pDataNode) {
    *pValue = fxv8::NewNullHelper(pIsolate);
    return;
  }

  *pValue =
      GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pDataNode);
}

void CJX_Object::ScriptSomMandatory(v8::Isolate* pIsolate,
                                    v8::Local<v8::Value>* pValue,
                                    bool bSetting,
                                    XFA_Attribute eAttribute) {
  CXFA_Validate* validate =
      ToNode(object_.Get())->GetOrCreateValidateIfPossible();
  if (!validate)
    return;

  if (bSetting) {
    validate->SetNullTest(fxv8::ReentrantToWideStringHelper(pIsolate, *pValue));
    return;
  }

  *pValue = fxv8::NewStringHelper(
      pIsolate, XFA_AttributeValueToName(validate->GetNullTest()));
}

void CJX_Object::ScriptSomInstanceIndex(v8::Isolate* pIsolate,
                                        v8::Local<v8::Value>* pValue,
                                        bool bSetting,
                                        XFA_Attribute eAttribute) {
  if (!bSetting) {
    *pValue =
        fxv8::NewNumberHelper(pIsolate, Subform_and_SubformSet_InstanceIndex());
    return;
  }

  int32_t iTo = fxv8::ReentrantToInt32Helper(pIsolate, *pValue);
  int32_t iFrom = Subform_and_SubformSet_InstanceIndex();
  CXFA_Node* pManagerNode = nullptr;
  for (CXFA_Node* pNode = GetXFANode()->GetPrevSibling(); pNode;
       pNode = pNode->GetPrevSibling()) {
    if (pNode->GetElementType() == XFA_Element::InstanceManager) {
      pManagerNode = pNode;
      break;
    }
  }
  if (!pManagerNode)
    return;

  auto* mgr = static_cast<CJX_InstanceManager*>(pManagerNode->JSObject());
  mgr->MoveInstance(iTo, iFrom);
  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
  if (!pNotify)
    return;

  CXFA_Node* pToInstance = pManagerNode->GetItemIfExists(iTo);
  if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform) {
    pNotify->RunSubformIndexChange(pToInstance);
  }

  CXFA_Node* pFromInstance = pManagerNode->GetItemIfExists(iFrom);
  if (pFromInstance &&
      pFromInstance->GetElementType() == XFA_Element::Subform) {
    pNotify->RunSubformIndexChange(pFromInstance);
  }
}

void CJX_Object::ScriptSubmitFormatMode(v8::Isolate* pIsolate,
                                        v8::Local<v8::Value>* pValue,
                                        bool bSetting,
                                        XFA_Attribute eAttribute) {}

CJX_Object::CalcData::CalcData() = default;

CJX_Object::CalcData::~CalcData() = default;

void CJX_Object::CalcData::Trace(cppgc::Visitor* visitor) const {
  ContainerTrace(visitor, m_Globals);
}
