blob: cd196f585d8eed49d75a1d2bd855832546fbe7ac [file] [log] [blame]
// 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 "../../../foxitlib.h"
#include "../common/xfa_utils.h"
#include "../common/xfa_object.h"
#include "../common/xfa_document.h"
#include "../common/xfa_parser.h"
#include "../common/xfa_script.h"
#include "../common/xfa_docdata.h"
#include "../common/xfa_doclayout.h"
#include "../common/xfa_debug.h"
#include "../common/xfa_localemgr.h"
#include "../common/xfa_fm2jsapi.h"
#include "xfa_debug_parser.h"
#include "xfa_script_imp.h"
#include "xfa_script_resolveprocessor.h"
#include "xfa_script_nodehelper.h"
CXFA_ScriptContext::CXFA_ScriptContext(CXFA_Document* pDocument)
: m_pDocument(pDocument), m_hJsRuntime(NULL), m_hJsContext(NULL), m_hJsClass(NULL)
, m_pEventParam(NULL), m_pResolveProcessor(NULL), m_eScriptType(XFA_SCRIPTLANGTYPE_Unkown)
, m_hFM2JSContext(NULL), m_pThisObject(NULL), m_pScriptNodeArray(NULL)
, m_dwBuiltInInFlags(0)
, m_eRunAtType(XFA_ATTRIBUTEENUM_Client)
{
FX_memset(&m_JsGlobalClass, 0, sizeof(FXJSE_CLASS));
FX_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 (FX_INT32 i = 0; i < m_CacheListArray.GetSize(); i++) {
delete ((CXFA_NodeList*)m_CacheListArray[i]);
}
m_CacheListArray.RemoveAll();
if (m_dwBuiltInInFlags & XFA_JSBUILTIN_HasCount) {
FX_POSITION ps = m_JSBuiltInObjects.GetStartPosition();
while (ps) {
CFX_ByteString bsKey;
void* pValue = NULL;
m_JSBuiltInObjects.GetNextAssoc(ps, bsKey, pValue);
if (pValue) {
FXJSE_Value_Release((FXJSE_HVALUE)pValue);
}
}
m_JSBuiltInObjects.RemoveAll();
}
}
void CXFA_ScriptContext::Initialize(FXJSE_HRUNTIME hRuntime)
{
m_hJsRuntime = hRuntime;
DefineJsContext();
DefineJsClass();
m_pResolveProcessor = FX_NEW CXFA_ResolveProcessor;
}
void CXFA_ScriptContext::Release()
{
delete this;
}
FX_BOOL CXFA_ScriptContext::RunScript(XFA_SCRIPTLANGTYPE eScriptType, FX_WSTR 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;
FX_INT32 iFlags = XFA_FM2JS_Translate(wsScript, wsJavaScript, wsErrorInfo);
if(iFlags) {
FXJSE_Value_SetUndefined(hRetValue);
return FALSE;
}
btScript = FX_UTF8Encode(wsJavaScript.GetBuffer(), wsJavaScript.GetLength());
} else {
if ((m_dwBuiltInInFlags & XFA_JSBUILTIN_Initialized) == 0) {
m_dwBuiltInInFlags = XFA_JSBUILTIN_Initialized;
FX_POSITION ps = m_JSBuiltInObjects.GetStartPosition();
if (ps) {
FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(m_hJsContext);
while (ps) {
CFX_ByteString bsKey;
void* pValue;
m_JSBuiltInObjects.GetNextAssoc(ps, bsKey, pValue);
FXJSE_HVALUE hProp = FXJSE_Value_Create(m_hJsRuntime);
if (FXJSE_Value_GetObjectProp(hObject, bsKey, hProp)) {
m_JSBuiltInObjects.SetAt(bsKey, hProp);
FXJSE_Value_DeleteObjectProp(hObject, bsKey);
m_dwBuiltInInFlags |= XFA_JSBUILTIN_HasCount;
} else {
m_JSBuiltInObjects.RemoveKey(bsKey);
FXJSE_Value_Release(hProp);
}
}
FXJSE_Value_Release(hObject);
}
}
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, FX_BSTR 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((FX_LPCSTR)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 = (CXFA_Node*)lpScriptContext->GetThisObject();
if(lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
pRefNode = (CXFA_Node*)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, FX_WSTR propname, FXJSE_HVALUE hValue, FX_DWORD dwFlag, FX_BOOL bSetting)
{
XFA_RESOLVENODE_RS resolveRs;
FX_INT32 iRet = ResolveObjects(refNode, propname, resolveRs, dwFlag);
FX_BOOL bResult = FALSE;
if (iRet > 0) {
bResult = TRUE;
if(resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
FXJSE_HVALUE pValue = GetJSValueFromMap(resolveRs.nodes[0]);
FXJSE_Value_Set(hValue, pValue);
} else if(resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Attribute) {
XFA_LPCSCRIPTATTRIBUTEINFO lpAttributeInfo = resolveRs.pScriptAttribute;
if(lpAttributeInfo) {
(resolveRs.nodes[0]->*(lpAttributeInfo->lpfnCallback))(hValue, bSetting, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
}
}
}
return bResult;
}
void CXFA_ScriptContext::GlobalPropertyGetter(FXJSE_HOBJECT hObject, FX_BSTR 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((FX_LPCSTR)szPropName.GetPtr(), szPropName.GetLength());
if (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Formcalc) {
if(szPropName == FX_BSTRC(FOXIT_XFA_FM2JS_FORMCALC_RUNTIME)) {
XFA_FM2JS_GlobalPropertyGetter(lpScriptContext->m_hFM2JSContext, hValue);
return;
}
FX_UINT32 uHashCode = FX_HashCode_String_GetW(wsPropName, wsPropName.GetLength());
if(uHashCode != XFA_HASHCODE_Layout) {
CXFA_Object * pObject = lpScriptContext->GetDocument()->GetXFANode(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 = (CXFA_Node*)lpScriptContext->GetThisObject();
if(pOrginalObject->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
pRefNode = (CXFA_Node*)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((CXFA_Node *)pScriptObject, szPropName, hValue, TRUE)) {
return;
}
if (lpScriptContext->QueryBuiltinHValue(szPropName, hValue)) {
return;
}
IXFA_Notify* pNotify = pDoc->GetNotify();
if (!pNotify) {
return;
}
pNotify->GetDocProvider()->GetGlobalProperty(pNotify->GetHDOC(), szPropName, hValue);
}
void CXFA_ScriptContext::NormalPropertyGetter(FXJSE_HOBJECT hObject, FX_BSTR 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((FX_LPCSTR)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((CXFA_Node *)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((CXFA_Node *)pObject, wsPropName, hValue, dwFlag, FALSE);
}
if(bRet) {
return;
}
CXFA_Object* pScriptObject = lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
if (pScriptObject) {
bRet = lpScriptContext->QueryVariableHValue((CXFA_Node *)pScriptObject, szPropName, hValue, TRUE);
}
if (!bRet) {
FXJSE_Value_SetUndefined(hValue);
}
}
void CXFA_ScriptContext::NormalPropertySetter(FXJSE_HOBJECT hObject, FX_BSTR 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((FX_LPCSTR)szPropName.GetPtr(), szPropName.GetLength());
XFA_LPCSCRIPTATTRIBUTEINFO 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 = (CXFA_Node*)pObject;
CXFA_Node *pPropOrChild = NULL;
XFA_LPCELEMENTINFO 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}");
XFA_LPCSCRIPTATTRIBUTEINFO 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((CXFA_Node *)pScriptObject, szPropName, hValue, FALSE);
}
}
}
FX_INT32 CXFA_ScriptContext::NormalPropTypeGetter(FXJSE_HOBJECT hObject, FX_BSTR 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((FX_LPCSTR)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;
}
FX_INT32 CXFA_ScriptContext::GlobalPropTypeGetter(FXJSE_HOBJECT hObject, FX_BSTR 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((FX_LPCSTR)szPropName.GetPtr(), szPropName.GetLength());
if(XFA_GetMethodByName(objElement, wsPropName)) {
return FXJSE_ClassPropType_Method;
}
return FXJSE_ClassPropType_Property;
}
void CXFA_ScriptContext::NormalMethodCall(FXJSE_HOBJECT hThis, FX_BSTR 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((FX_LPCSTR)szFuncName.GetPtr(), szFuncName.GetLength());
XFA_LPCMETHODINFO 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());
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 = FX_NEW CXFA_ThisProxy(pSubform, pScriptNode);
FXJSE_HCONTEXT hVariablesContext = FXJSE_Context_Create(m_hJsRuntime, &m_JsGlobalVariablesClass, (CXFA_Object*)lpVariableNode);
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, FX_BSTR szPropName, FXJSE_HVALUE hValue, FX_BOOL bGetter)
{
if(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;
FX_LPVOID 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;
}
FX_BOOL CXFA_ScriptContext::QueryBuiltinHValue(FX_BSTR szPropName, FXJSE_HVALUE hValue)
{
void* pBuiltin = NULL;
if ((m_dwBuiltInInFlags & XFA_JSBUILTIN_HasCount) && m_JSBuiltInObjects.Lookup(szPropName, pBuiltin)) {
FXJSE_Value_Set(hValue, (FXJSE_HVALUE)pBuiltin);
return TRUE;
}
return FALSE;
}
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);
}
FXJSE_HCLASS CXFA_ScriptContext::GetJseNormalClass()
{
return m_hJsClass;
}
void CXFA_ScriptContext::AddJSBuiltinObject(XFA_LPCJSBUILTININFO pBuitinObject)
{
if (m_dwBuiltInInFlags & XFA_JSBUILTIN_Initialized) {
return;
}
m_JSBuiltInObjects.SetAt(pBuitinObject->pName, (void*)pBuitinObject);
}
FX_INT32 CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode, FX_WSTR 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 && (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings)) && refNode->IsNode()) {
m_upObjectArray.Add((CXFA_Node*)refNode);
}
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;
FX_INT32 nStart = 0;
FX_INT32 nLevel = 0;
FX_INT32 nRet = -1;
rndFind.m_pSC = this;
CXFA_ObjArray findNodes;
if (refNode != NULL) {
findNodes.Add(refNode);
} else {
findNodes.Add(m_pDocument->GetRoot());
}
FX_INT32 nNodes = 0;
while (TRUE) {
nNodes = findNodes.GetSize();
FX_INT32 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 = (CXFA_Node*)findNodes[0];
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() ? TRUE : FALSE, 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);
}
FX_INT32 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 = (CXFA_Node*)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() ? TRUE : FALSE, 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((CXFA_Node*)pObject);
}
FX_LPVOID 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;
}
FX_INT32 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);
}
FX_INT32 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 FX_NEW CXFA_ScriptContext(pDocument);
}
static const XFA_JSBUILTININFO gs_JSBUILTINData[] = {
{0x8108b9a9, "Number"},
{0xe07e3fbe, "Date"},
};
const FX_INT32 g_iJSBuiltinCount = sizeof(XFA_JSBUILTININFO) / sizeof(XFA_JSBUILTININFO);
XFA_LPCJSBUILTININFO XFA_GetJSBuiltinByHash(FX_UINT32 uHashCode)
{
FX_INT32 iStart = 0, iEnd = g_iJSBuiltinCount - 1, iMid;
do {
iMid = (iStart + iEnd) / 2;
XFA_LPCJSBUILTININFO pInfo = gs_JSBUILTINData + iMid;
if (uHashCode == pInfo->uUnicodeHash) {
return pInfo;
} else if (uHashCode < pInfo->uUnicodeHash) {
iEnd = iMid - 1;
} else {
iStart = iMid + 1;
}
} while (iStart <= iEnd);
return NULL;
}