// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "xfa/fxfa/parser/xfa_script_imp.h"

#include "core/include/fxcrt/fx_ext.h"
#include "xfa/fxfa/fm2js/xfa_fm2jsapi.h"
#include "xfa/fxfa/parser/xfa_docdata.h"
#include "xfa/fxfa/parser/xfa_doclayout.h"
#include "xfa/fxfa/parser/xfa_document.h"
#include "xfa/fxfa/parser/xfa_localemgr.h"
#include "xfa/fxfa/parser/xfa_object.h"
#include "xfa/fxfa/parser/xfa_parser.h"
#include "xfa/fxfa/parser/xfa_script.h"
#include "xfa/fxfa/parser/xfa_script_nodehelper.h"
#include "xfa/fxfa/parser/xfa_script_resolveprocessor.h"
#include "xfa/fxfa/parser/xfa_utils.h"
#include "xfa/fxjse/cfxjse_arguments.h"

CXFA_ScriptContext::CXFA_ScriptContext(CXFA_Document* pDocument)
    : m_pDocument(pDocument),
      m_hJsContext(nullptr),
      m_hJsRuntime(nullptr),
      m_hJsClass(nullptr),
      m_eScriptType(XFA_SCRIPTLANGTYPE_Unkown),
      m_pScriptNodeArray(nullptr),
      m_pResolveProcessor(nullptr),
      m_hFM2JSContext(nullptr),
      m_pThisObject(nullptr),
      m_dwBuiltInInFlags(0),
      m_eRunAtType(XFA_ATTRIBUTEENUM_Client) {
  FXSYS_memset(&m_JsGlobalClass, 0, sizeof(FXJSE_CLASS));
  FXSYS_memset(&m_JsNormalClass, 0, sizeof(FXJSE_CLASS));
}
CXFA_ScriptContext::~CXFA_ScriptContext() {
  FX_POSITION ps = m_mapXFAToHValue.GetStartPosition();
  while (ps) {
    CXFA_Object* pXFAObj;
    FXJSE_HVALUE pValue;
    m_mapXFAToHValue.GetNextAssoc(ps, pXFAObj, pValue);
    FXJSE_Value_Release(pValue);
  }
  m_mapXFAToHValue.RemoveAll();
  ReleaseVariablesMap();
  if (m_hFM2JSContext) {
    XFA_FM2JS_ContextRelease(m_hFM2JSContext);
    m_hFM2JSContext = NULL;
  }
  if (m_hJsContext) {
    FXJSE_Context_Release(m_hJsContext);
    m_hJsContext = NULL;
  }
  if (m_pResolveProcessor) {
    delete m_pResolveProcessor;
    m_pResolveProcessor = NULL;
  }
  m_upObjectArray.RemoveAll();
  for (int32_t i = 0; i < m_CacheListArray.GetSize(); i++) {
    delete ((CXFA_NodeList*)m_CacheListArray[i]);
  }
  m_CacheListArray.RemoveAll();
}
void CXFA_ScriptContext::Initialize(FXJSE_HRUNTIME hRuntime) {
  m_hJsRuntime = hRuntime;
  DefineJsContext();
  DefineJsClass();
  m_pResolveProcessor = new CXFA_ResolveProcessor;
}
void CXFA_ScriptContext::Release() {
  delete this;
}
FX_BOOL CXFA_ScriptContext::RunScript(XFA_SCRIPTLANGTYPE eScriptType,
                                      const CFX_WideStringC& wsScript,
                                      FXJSE_HVALUE hRetValue,
                                      CXFA_Object* pThisObject) {
  CFX_ByteString btScript;
  XFA_SCRIPTLANGTYPE eSaveType = m_eScriptType;
  m_eScriptType = eScriptType;
  if (eScriptType == XFA_SCRIPTLANGTYPE_Formcalc) {
    if (!m_hFM2JSContext) {
      m_hFM2JSContext = XFA_FM2JS_ContextCreate();
      XFA_FM2JS_ContextInitialize(m_hFM2JSContext, m_hJsRuntime, m_hJsContext,
                                  m_pDocument);
    }
    CFX_WideTextBuf wsJavaScript;
    CFX_WideString wsErrorInfo;
    int32_t iFlags = XFA_FM2JS_Translate(wsScript, wsJavaScript, wsErrorInfo);
    if (iFlags) {
      FXJSE_Value_SetUndefined(hRetValue);
      return FALSE;
    }
    btScript =
        FX_UTF8Encode(wsJavaScript.GetBuffer(), wsJavaScript.GetLength());
  } else {
    btScript = FX_UTF8Encode(wsScript.GetPtr(), wsScript.GetLength());
  }
  CXFA_Object* pOriginalObject = m_pThisObject;
  m_pThisObject = pThisObject;
  FXJSE_HVALUE pValue = pThisObject ? GetJSValueFromMap(pThisObject) : NULL;
  FX_BOOL bRet = FXJSE_ExecuteScript(m_hJsContext, btScript, hRetValue, pValue);
  m_pThisObject = pOriginalObject;
  m_eScriptType = eSaveType;
  return bRet;
}
void CXFA_ScriptContext::GlobalPropertySetter(FXJSE_HOBJECT hObject,
                                              const CFX_ByteStringC& szPropName,
                                              FXJSE_HVALUE hValue) {
  CXFA_Object* lpOrginalNode =
      (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
  CXFA_Document* pDoc = lpOrginalNode->GetDocument();
  CXFA_ScriptContext* lpScriptContext =
      (CXFA_ScriptContext*)pDoc->GetScriptContext();
  CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode);
  CFX_WideString wsPropName = CFX_WideString::FromUTF8(
      (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
  FX_DWORD dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings |
                    XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
                    XFA_RESOLVENODE_Attributes;
  CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject());
  if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    pRefNode = ToNode(lpCurNode);
  }
  if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
                                       TRUE)) {
    return;
  }
  if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    if (FXJSE_Value_IsUndefined(hValue)) {
      FXJSE_Value_SetObjectOwnProp(hObject, szPropName, hValue);
      return;
    }
  }
  IXFA_Notify* pNotify = pDoc->GetNotify();
  if (!pNotify) {
    return;
  }
  pNotify->GetDocProvider()->SetGlobalProperty(pNotify->GetHDOC(), szPropName,
                                               hValue);
}
FX_BOOL CXFA_ScriptContext::QueryNodeByFlag(CXFA_Node* refNode,
                                            const CFX_WideStringC& propname,
                                            FXJSE_HVALUE hValue,
                                            FX_DWORD dwFlag,
                                            FX_BOOL bSetting) {
  if (!refNode)
    return false;
  XFA_RESOLVENODE_RS resolveRs;
  if (ResolveObjects(refNode, propname, resolveRs, dwFlag) <= 0)
    return false;
  if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
    FXJSE_HVALUE pValue = GetJSValueFromMap(resolveRs.nodes[0]);
    FXJSE_Value_Set(hValue, pValue);
    return true;
  }
  if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Attribute) {
    const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = resolveRs.pScriptAttribute;
    if (lpAttributeInfo) {
      (resolveRs.nodes[0]->*(lpAttributeInfo->lpfnCallback))(
          hValue, bSetting, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
    }
  }
  return true;
}
void CXFA_ScriptContext::GlobalPropertyGetter(FXJSE_HOBJECT hObject,
                                              const CFX_ByteStringC& szPropName,
                                              FXJSE_HVALUE hValue) {
  CXFA_Object* pOrginalObject =
      (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
  CXFA_Document* pDoc = pOrginalObject->GetDocument();
  CXFA_ScriptContext* lpScriptContext =
      (CXFA_ScriptContext*)pDoc->GetScriptContext();
  CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(pOrginalObject);
  CFX_WideString wsPropName = CFX_WideString::FromUTF8(
      (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
  if (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Formcalc) {
    if (szPropName == FOXIT_XFA_FM2JS_FORMCALC_RUNTIME) {
      XFA_FM2JS_GlobalPropertyGetter(lpScriptContext->m_hFM2JSContext, hValue);
      return;
    }
    uint32_t uHashCode =
        FX_HashCode_String_GetW(wsPropName, wsPropName.GetLength());
    if (uHashCode != XFA_HASHCODE_Layout) {
      CXFA_Object* pObject =
          lpScriptContext->GetDocument()->GetXFAObject(uHashCode);
      if (pObject) {
        FXJSE_Value_Set(hValue, lpScriptContext->GetJSValueFromMap(pObject));
        return;
      }
    }
  }
  FX_DWORD dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
                    XFA_RESOLVENODE_Attributes;
  CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject());
  if (pOrginalObject->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    pRefNode = ToNode(lpCurNode);
  }
  if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
                                       FALSE)) {
    return;
  }
  dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings;
  if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
                                       FALSE)) {
    return;
  }
  CXFA_Object* pScriptObject =
      lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
  if (pScriptObject &&
      lpScriptContext->QueryVariableHValue(pScriptObject->AsNode(), szPropName,
                                           hValue, TRUE)) {
    return;
  }
  IXFA_Notify* pNotify = pDoc->GetNotify();
  if (!pNotify) {
    return;
  }
  pNotify->GetDocProvider()->GetGlobalProperty(pNotify->GetHDOC(), szPropName,
                                               hValue);
}
void CXFA_ScriptContext::NormalPropertyGetter(FXJSE_HOBJECT hObject,
                                              const CFX_ByteStringC& szPropName,
                                              FXJSE_HVALUE hValue) {
  CXFA_Object* pOrginalObject =
      (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
  if (pOrginalObject == NULL) {
    FXJSE_Value_SetUndefined(hValue);
    return;
  }
  CFX_WideString wsPropName = CFX_WideString::FromUTF8(
      (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
  CXFA_ScriptContext* lpScriptContext =
      (CXFA_ScriptContext*)pOrginalObject->GetDocument()->GetScriptContext();
  CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOrginalObject);
  if (wsPropName == FX_WSTRC(L"xfa")) {
    FXJSE_HVALUE pValue = lpScriptContext->GetJSValueFromMap(
        lpScriptContext->GetDocument()->GetRoot());
    FXJSE_Value_Set(hValue, pValue);
    return;
  }
  FX_DWORD dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
                    XFA_RESOLVENODE_Attributes;
  FX_BOOL bRet = lpScriptContext->QueryNodeByFlag(ToNode(pObject), wsPropName,
                                                  hValue, dwFlag, FALSE);
  if (bRet) {
    return;
  }
  if (pObject == lpScriptContext->GetThisObject() ||
      (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Javascript &&
       !lpScriptContext->IsStrictScopeInJavaScript())) {
    dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings;
    bRet = lpScriptContext->QueryNodeByFlag(ToNode(pObject), wsPropName, hValue,
                                            dwFlag, FALSE);
  }
  if (bRet) {
    return;
  }
  CXFA_Object* pScriptObject =
      lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
  if (pScriptObject) {
    bRet = lpScriptContext->QueryVariableHValue(ToNode(pScriptObject),
                                                szPropName, hValue, TRUE);
  }
  if (!bRet) {
    FXJSE_Value_SetUndefined(hValue);
  }
}
void CXFA_ScriptContext::NormalPropertySetter(FXJSE_HOBJECT hObject,
                                              const CFX_ByteStringC& szPropName,
                                              FXJSE_HVALUE hValue) {
  CXFA_Object* pOrginalObject =
      (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
  if (pOrginalObject == NULL) {
    return;
  }
  CXFA_ScriptContext* lpScriptContext =
      (CXFA_ScriptContext*)pOrginalObject->GetDocument()->GetScriptContext();
  CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOrginalObject);
  CFX_WideString wsPropName = CFX_WideString::FromUTF8(
      (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
  const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo =
      XFA_GetScriptAttributeByName(pObject->GetClassID(), wsPropName);
  if (lpAttributeInfo) {
    (pObject->*(lpAttributeInfo->lpfnCallback))(
        hValue, TRUE, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
  } else {
    if (pObject->IsNode()) {
      if (wsPropName.GetAt(0) == '#') {
        wsPropName = wsPropName.Right(wsPropName.GetLength() - 1);
      }
      CXFA_Node* pNode = ToNode(pObject);
      CXFA_Node* pPropOrChild = NULL;
      const XFA_ELEMENTINFO* lpElementInfo = XFA_GetElementByName(wsPropName);
      if (lpElementInfo) {
        pPropOrChild = pNode->GetProperty(0, lpElementInfo->eName);
      } else {
        pPropOrChild = pNode->GetFirstChildByName(wsPropName);
      }
      if (pPropOrChild) {
        CFX_WideString wsDefaultName = FX_WSTRC(L"{default}");
        const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo =
            XFA_GetScriptAttributeByName(pPropOrChild->GetClassID(),
                                         wsDefaultName);
        if (lpAttributeInfo) {
          (pPropOrChild->*(lpAttributeInfo->lpfnCallback))(
              hValue, TRUE, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
          return;
        }
      }
    }
    CXFA_Object* pScriptObject =
        lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
    if (pScriptObject) {
      lpScriptContext->QueryVariableHValue(ToNode(pScriptObject), szPropName,
                                           hValue, FALSE);
    }
  }
}
int32_t CXFA_ScriptContext::NormalPropTypeGetter(
    FXJSE_HOBJECT hObject,
    const CFX_ByteStringC& szPropName,
    FX_BOOL bQueryIn) {
  CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
  if (pObject == NULL) {
    return FXJSE_ClassPropType_None;
  }
  CXFA_ScriptContext* lpScriptContext =
      (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
  pObject = lpScriptContext->GetVariablesThis(pObject);
  XFA_ELEMENT objElement = pObject->GetClassID();
  CFX_WideString wsPropName = CFX_WideString::FromUTF8(
      (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
  if (XFA_GetMethodByName(objElement, wsPropName)) {
    return FXJSE_ClassPropType_Method;
  }
  if (bQueryIn && !XFA_GetScriptAttributeByName(objElement, wsPropName)) {
    return FXJSE_ClassPropType_None;
  }
  return FXJSE_ClassPropType_Property;
}
int32_t CXFA_ScriptContext::GlobalPropTypeGetter(
    FXJSE_HOBJECT hObject,
    const CFX_ByteStringC& szPropName,
    FX_BOOL bQueryIn) {
  CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
  if (pObject == NULL) {
    return FXJSE_ClassPropType_None;
  }
  CXFA_ScriptContext* lpScriptContext =
      (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
  pObject = lpScriptContext->GetVariablesThis(pObject);
  XFA_ELEMENT objElement = pObject->GetClassID();
  CFX_WideString wsPropName = CFX_WideString::FromUTF8(
      (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
  if (XFA_GetMethodByName(objElement, wsPropName)) {
    return FXJSE_ClassPropType_Method;
  }
  return FXJSE_ClassPropType_Property;
}
void CXFA_ScriptContext::NormalMethodCall(FXJSE_HOBJECT hThis,
                                          const CFX_ByteStringC& szFuncName,
                                          CFXJSE_Arguments& args) {
  CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hThis, NULL);
  if (pObject == NULL) {
    return;
  }
  CXFA_ScriptContext* lpScriptContext =
      (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
  pObject = lpScriptContext->GetVariablesThis(pObject);
  CFX_WideString wsFunName = CFX_WideString::FromUTF8(
      (const FX_CHAR*)szFuncName.GetPtr(), szFuncName.GetLength());
  const XFA_METHODINFO* lpMethodInfo =
      XFA_GetMethodByName(pObject->GetClassID(), wsFunName);
  if (NULL == lpMethodInfo) {
    return;
  }
  (pObject->*(lpMethodInfo->lpfnCallback))(&args);
}
FX_BOOL CXFA_ScriptContext::IsStrictScopeInJavaScript() {
  return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping);
}
XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() {
  return m_eScriptType;
}
void CXFA_ScriptContext::DefineJsContext() {
  m_JsGlobalClass.constructor = NULL;
  m_JsGlobalClass.name = "Root";
  m_JsGlobalClass.propNum = 0;
  m_JsGlobalClass.properties = NULL;
  m_JsGlobalClass.methNum = 0;
  m_JsGlobalClass.methods = NULL;
  m_JsGlobalClass.dynPropGetter = CXFA_ScriptContext::GlobalPropertyGetter;
  m_JsGlobalClass.dynPropSetter = CXFA_ScriptContext::GlobalPropertySetter;
  m_JsGlobalClass.dynPropTypeGetter = CXFA_ScriptContext::GlobalPropTypeGetter;
  m_JsGlobalClass.dynPropDeleter = NULL;
  m_JsGlobalClass.dynMethodCall = CXFA_ScriptContext::NormalMethodCall;
  m_hJsContext = FXJSE_Context_Create(m_hJsRuntime, &m_JsGlobalClass,
                                      m_pDocument->GetRoot());
  RemoveBuiltInObjs(m_hJsContext);
  FXJSE_Context_EnableCompatibleMode(
      m_hJsContext, FXJSE_COMPATIBLEMODEFLAG_CONSTRUCTOREXTRAMETHODS);
}
FXJSE_HCONTEXT CXFA_ScriptContext::CreateVariablesContext(
    CXFA_Node* pScriptNode,
    CXFA_Node* pSubform) {
  if (pScriptNode == NULL || pSubform == NULL) {
    return NULL;
  }
  if (m_mapVariableToHValue.GetCount() == 0) {
    m_JsGlobalVariablesClass.constructor = NULL;
    m_JsGlobalVariablesClass.name = "XFAScriptObject";
    m_JsGlobalVariablesClass.propNum = 0;
    m_JsGlobalVariablesClass.properties = NULL;
    m_JsGlobalVariablesClass.methNum = 0;
    m_JsGlobalVariablesClass.methods = NULL;
    m_JsGlobalVariablesClass.dynPropGetter =
        CXFA_ScriptContext::GlobalPropertyGetter;
    m_JsGlobalVariablesClass.dynPropSetter =
        CXFA_ScriptContext::GlobalPropertySetter;
    m_JsGlobalVariablesClass.dynPropTypeGetter =
        CXFA_ScriptContext::NormalPropTypeGetter;
    m_JsGlobalVariablesClass.dynPropDeleter = NULL;
    m_JsGlobalVariablesClass.dynMethodCall =
        CXFA_ScriptContext::NormalMethodCall;
  }
  CXFA_ThisProxy* lpVariableNode = new CXFA_ThisProxy(pSubform, pScriptNode);
  FXJSE_HCONTEXT hVariablesContext = FXJSE_Context_Create(
      m_hJsRuntime, &m_JsGlobalVariablesClass, (CXFA_Object*)lpVariableNode);
  RemoveBuiltInObjs(hVariablesContext);
  FXJSE_Context_EnableCompatibleMode(
      hVariablesContext, FXJSE_COMPATIBLEMODEFLAG_CONSTRUCTOREXTRAMETHODS);
  m_mapVariableToHValue.SetAt(pScriptNode, hVariablesContext);
  return hVariablesContext;
}
CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject,
                                                  FX_BOOL bScriptNode) {
  if (pObject->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    return bScriptNode ? ((CXFA_ThisProxy*)pObject)->GetScriptNode()
                       : ((CXFA_ThisProxy*)pObject)->GetThisNode();
  }
  return pObject;
}
FX_BOOL CXFA_ScriptContext::RunVariablesScript(CXFA_Node* pScriptNode) {
  if (pScriptNode == NULL) {
    return FALSE;
  }
  if (pScriptNode->GetClassID() == XFA_ELEMENT_Script) {
    CXFA_Node* pParent = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent);
    if (!pParent || pParent->GetClassID() != XFA_ELEMENT_Variables) {
      return FALSE;
    }
    if (m_mapVariableToHValue.GetValueAt(pScriptNode)) {
      return TRUE;
    }
    CXFA_Node* pTextNode = pScriptNode->GetNodeItem(XFA_NODEITEM_FirstChild);
    if (!pTextNode) {
      return FALSE;
    }
    CFX_WideStringC wsScript;
    if (!pTextNode->TryCData(XFA_ATTRIBUTE_Value, wsScript)) {
      return FALSE;
    }
    CFX_ByteString btScript =
        FX_UTF8Encode(wsScript.GetPtr(), wsScript.GetLength());
    FXJSE_HVALUE hRetValue = FXJSE_Value_Create(m_hJsRuntime);
    CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent);
    FXJSE_HCONTEXT hVariablesContext =
        CreateVariablesContext(pScriptNode, pThisObject);
    CXFA_Object* pOriginalObject = m_pThisObject;
    m_pThisObject = pThisObject;
    FX_BOOL bRet = FXJSE_ExecuteScript(hVariablesContext, btScript, hRetValue);
    m_pThisObject = pOriginalObject;
    FXJSE_Value_Release(hRetValue);
    return bRet;
  }
  return TRUE;
}
FX_BOOL CXFA_ScriptContext::QueryVariableHValue(
    CXFA_Node* pScriptNode,
    const CFX_ByteStringC& szPropName,
    FXJSE_HVALUE hValue,
    FX_BOOL bGetter) {
  if (!pScriptNode || pScriptNode->GetClassID() != XFA_ELEMENT_Script) {
    return FALSE;
  }
  CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent);
  if (!variablesNode || variablesNode->GetClassID() != XFA_ELEMENT_Variables) {
    return FALSE;
  }
  FX_BOOL bRes = FALSE;
  void* lpVariables = m_mapVariableToHValue.GetValueAt(pScriptNode);
  if (lpVariables) {
    FXJSE_HCONTEXT hVariableContext = (FXJSE_HCONTEXT)lpVariables;
    FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(hVariableContext);
    FXJSE_HVALUE hVariableValue = FXJSE_Value_Create(m_hJsRuntime);
    if (!bGetter) {
      FXJSE_Value_SetObjectOwnProp(hObject, szPropName, hValue);
      bRes = TRUE;
    } else if (FXJSE_Value_ObjectHasOwnProp(hObject, szPropName, FALSE)) {
      FXJSE_Value_GetObjectProp(hObject, szPropName, hVariableValue);
      if (FXJSE_Value_IsFunction(hVariableValue)) {
        FXJSE_Value_SetFunctionBind(hValue, hVariableValue, hObject);
      } else if (bGetter) {
        FXJSE_Value_Set(hValue, hVariableValue);
      } else {
        FXJSE_Value_Set(hVariableValue, hValue);
      }
      bRes = TRUE;
    }
    FXJSE_Value_Release(hVariableValue);
    FXJSE_Value_Release(hObject);
  }
  return bRes;
}
void CXFA_ScriptContext::ReleaseVariablesMap() {
  FX_POSITION ps = m_mapVariableToHValue.GetStartPosition();
  while (ps) {
    CXFA_Object* pScriptNode;
    FXJSE_HCONTEXT hVariableContext;
    m_mapVariableToHValue.GetNextAssoc(ps, pScriptNode, hVariableContext);
    FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(hVariableContext);
    CXFA_Object* lpCurNode = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    if (lpCurNode) {
      delete (CXFA_ThisProxy*)lpCurNode;
      lpCurNode = NULL;
    }
    FXJSE_Value_Release(hObject);
    FXJSE_Context_Release(hVariableContext);
    hVariableContext = NULL;
  }
  m_mapVariableToHValue.RemoveAll();
}
void CXFA_ScriptContext::DefineJsClass() {
  m_JsNormalClass.constructor = NULL;
  m_JsNormalClass.name = "XFAObject";
  m_JsNormalClass.propNum = 0;
  m_JsNormalClass.properties = NULL;
  m_JsNormalClass.methNum = 0;
  m_JsNormalClass.methods = NULL;
  m_JsNormalClass.dynPropGetter = CXFA_ScriptContext::NormalPropertyGetter;
  m_JsNormalClass.dynPropSetter = CXFA_ScriptContext::NormalPropertySetter;
  m_JsNormalClass.dynPropTypeGetter = CXFA_ScriptContext::NormalPropTypeGetter;
  m_JsNormalClass.dynPropDeleter = NULL;
  m_JsNormalClass.dynMethodCall = CXFA_ScriptContext::NormalMethodCall;
  m_hJsClass = FXJSE_DefineClass(m_hJsContext, &m_JsNormalClass);
}
void CXFA_ScriptContext::RemoveBuiltInObjs(FXJSE_HCONTEXT jsContext) const {
  static const CFX_ByteStringC OBJ_NAME[2] = {"Number", "Date"};
  FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(jsContext);
  FXJSE_HVALUE hProp = FXJSE_Value_Create(m_hJsRuntime);
  for (int i = 0; i < 2; ++i) {
    if (FXJSE_Value_GetObjectProp(hObject, OBJ_NAME[i], hProp))
      FXJSE_Value_DeleteObjectProp(hObject, OBJ_NAME[i]);
  }
  FXJSE_Value_Release(hProp);
  FXJSE_Value_Release(hObject);
}
FXJSE_HCLASS CXFA_ScriptContext::GetJseNormalClass() {
  return m_hJsClass;
}
int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode,
                                           const CFX_WideStringC& wsExpression,
                                           XFA_RESOLVENODE_RS& resolveNodeRS,
                                           FX_DWORD dwStyles,
                                           CXFA_Node* bindNode) {
  if (wsExpression.IsEmpty()) {
    return 0;
  }
  if (m_eScriptType != XFA_SCRIPTLANGTYPE_Formcalc ||
      (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) {
    m_upObjectArray.RemoveAll();
  }
  if (refNode && refNode->IsNode() &&
      (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) {
    m_upObjectArray.Add(refNode->AsNode());
  }
  FX_BOOL bNextCreate = FALSE;
  if (dwStyles & XFA_RESOLVENODE_CreateNode) {
    m_pResolveProcessor->GetNodeHelper()->XFA_SetCreateNodeType(bindNode);
  }
  m_pResolveProcessor->GetNodeHelper()->m_pCreateParent = NULL;
  m_pResolveProcessor->GetNodeHelper()->m_iCurAllStart = -1;
  CXFA_ResolveNodesData rndFind;
  int32_t nStart = 0;
  int32_t nLevel = 0;
  int32_t nRet = -1;
  rndFind.m_pSC = this;
  CXFA_ObjArray findNodes;
  findNodes.Add(refNode ? refNode : m_pDocument->GetRoot());
  int32_t nNodes = 0;
  while (TRUE) {
    nNodes = findNodes.GetSize();
    int32_t i = 0;
    rndFind.m_dwStyles = dwStyles;
    m_pResolveProcessor->m_iCurStart = nStart;
    nStart = m_pResolveProcessor->XFA_ResolveNodes_GetFilter(wsExpression,
                                                             nStart, rndFind);
    if (nStart < 1) {
      if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) {
        CXFA_Node* pDataNode = NULL;
        nStart = m_pResolveProcessor->GetNodeHelper()->m_iCurAllStart;
        if (nStart != -1) {
          pDataNode = m_pDocument->GetNotBindNode(findNodes);
          if (pDataNode) {
            findNodes.RemoveAll();
            findNodes.Add(pDataNode);
            break;
          }
        } else {
          pDataNode = findNodes[0]->AsNode();
          findNodes.RemoveAll();
          findNodes.Add(pDataNode);
          break;
        }
        dwStyles |= XFA_RESOLVENODE_Bind;
        findNodes.RemoveAll();
        findNodes.Add(m_pResolveProcessor->GetNodeHelper()->m_pAllStartParent);
        continue;
      } else {
        break;
      }
    }
    if (bNextCreate) {
      FX_BOOL bCreate =
          m_pResolveProcessor->GetNodeHelper()->XFA_ResolveNodes_CreateNode(
              rndFind.m_wsName, rndFind.m_wsCondition,
              nStart == wsExpression.GetLength(), this);
      if (bCreate) {
        continue;
      } else {
        break;
      }
    }
    CXFA_ObjArray retNodes;
    while (i < nNodes) {
      FX_BOOL bDataBind = FALSE;
      if (((dwStyles & XFA_RESOLVENODE_Bind) ||
           (dwStyles & XFA_RESOLVENODE_CreateNode)) &&
          nNodes > 1) {
        CXFA_ResolveNodesData rndBind;
        m_pResolveProcessor->XFA_ResolveNodes_GetFilter(wsExpression, nStart,
                                                        rndBind);
        m_pResolveProcessor->XFA_ResolveNode_SetIndexDataBind(
            rndBind.m_wsCondition, i, nNodes);
        bDataBind = TRUE;
      }
      rndFind.m_CurNode = findNodes[i++];
      rndFind.m_nLevel = nLevel;
      rndFind.m_dwFlag = XFA_RESOVENODE_RSTYPE_Nodes;
      nRet = m_pResolveProcessor->XFA_ResolveNodes(rndFind);
      if (nRet < 1) {
        continue;
      }
      if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute &&
          rndFind.m_pScriptAttribute && nStart < wsExpression.GetLength()) {
        FXJSE_HVALUE hValue = FXJSE_Value_Create(m_hJsRuntime);
        (rndFind.m_Nodes[0]->*(rndFind.m_pScriptAttribute->lpfnCallback))(
            hValue, FALSE,
            (XFA_ATTRIBUTE)rndFind.m_pScriptAttribute->eAttribute);
        rndFind.m_Nodes.SetAt(0,
                              (CXFA_Object*)FXJSE_Value_ToObject(hValue, NULL));
        FXJSE_Value_Release(hValue);
      }
      int32_t iSize = m_upObjectArray.GetSize();
      if (iSize) {
        m_upObjectArray.RemoveAt(iSize - 1);
      }
      retNodes.Append(rndFind.m_Nodes);
      rndFind.m_Nodes.RemoveAll();
      if (bDataBind) {
        break;
      }
    }
    findNodes.RemoveAll();
    nNodes = retNodes.GetSize();
    if (nNodes < 1) {
      if (dwStyles & XFA_RESOLVENODE_CreateNode) {
        bNextCreate = TRUE;
        if (m_pResolveProcessor->GetNodeHelper()->m_pCreateParent == NULL) {
          m_pResolveProcessor->GetNodeHelper()->m_pCreateParent =
              ToNode(rndFind.m_CurNode);
          m_pResolveProcessor->GetNodeHelper()->m_iCreateCount = 1;
        }
        FX_BOOL bCreate =
            m_pResolveProcessor->GetNodeHelper()->XFA_ResolveNodes_CreateNode(
                rndFind.m_wsName, rndFind.m_wsCondition,
                nStart == wsExpression.GetLength(), this);
        if (bCreate) {
          continue;
        } else {
          break;
        }
      } else {
        break;
      }
    }
    findNodes.Copy(retNodes);
    rndFind.m_Nodes.RemoveAll();
    if (nLevel == 0) {
      dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
    }
    nLevel++;
  }
  if (!bNextCreate) {
    resolveNodeRS.dwFlags = rndFind.m_dwFlag;
    if (nNodes > 0) {
      resolveNodeRS.nodes.Append(findNodes);
    }
    if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute) {
      resolveNodeRS.pScriptAttribute = rndFind.m_pScriptAttribute;
      return 1;
    }
  }
  if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind |
                  XFA_RESOLVENODE_BindNew)) {
    m_pResolveProcessor->XFA_ResolveNode_SetResultCreateNode(
        resolveNodeRS, rndFind.m_wsCondition);
    if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) {
      resolveNodeRS.dwFlags = XFA_RESOVENODE_RSTYPE_ExistNodes;
    }
    return resolveNodeRS.nodes.GetSize();
  }
  return nNodes;
}
FXJSE_HVALUE CXFA_ScriptContext::GetJSValueFromMap(CXFA_Object* pObject) {
  if (!pObject) {
    return NULL;
  }
  if (pObject->IsNode()) {
    RunVariablesScript(pObject->AsNode());
  }
  void* pValue = m_mapXFAToHValue.GetValueAt(pObject);
  if (pValue == NULL) {
    FXJSE_HVALUE jsHvalue = FXJSE_Value_Create(m_hJsRuntime);
    FXJSE_Value_SetObject(jsHvalue, pObject, m_hJsClass);
    m_mapXFAToHValue.SetAt(pObject, jsHvalue);
    pValue = jsHvalue;
  }
  return (FXJSE_HVALUE)pValue;
}
int32_t CXFA_ScriptContext::GetIndexByName(CXFA_Node* refNode) {
  CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
  return lpNodeHelper->XFA_GetIndex(refNode, XFA_LOGIC_Transparent,
                                    lpNodeHelper->XFA_NodeIsProperty(refNode),
                                    FALSE);
}
int32_t CXFA_ScriptContext::GetIndexByClassName(CXFA_Node* refNode) {
  CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
  return lpNodeHelper->XFA_GetIndex(refNode, XFA_LOGIC_Transparent,
                                    lpNodeHelper->XFA_NodeIsProperty(refNode),
                                    TRUE);
}
void CXFA_ScriptContext::GetSomExpression(CXFA_Node* refNode,
                                          CFX_WideString& wsExpression) {
  CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
  lpNodeHelper->XFA_GetNameExpression(refNode, wsExpression, TRUE,
                                      XFA_LOGIC_Transparent);
}
void CXFA_ScriptContext::SetNodesOfRunScript(CXFA_NodeArray* pArray) {
  m_pScriptNodeArray = pArray;
}
void CXFA_ScriptContext::AddNodesOfRunScript(const CXFA_NodeArray& nodes) {
  if (!m_pScriptNodeArray) {
    return;
  }
  if (nodes.GetSize() > 0) {
    m_pScriptNodeArray->Copy(nodes);
  }
}
void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) {
  if (!m_pScriptNodeArray) {
    return;
  }
  if (m_pScriptNodeArray->Find(pNode) == -1) {
    m_pScriptNodeArray->Add(pNode);
  }
}
IXFA_ScriptContext* XFA_ScriptContext_Create(CXFA_Document* pDocument) {
  return new CXFA_ScriptContext(pDocument);
}
