Home | History | Annotate | Download | only in parser
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/src/foxitlib.h"
      8 #include "xfa/src/fxfa/src/common/xfa_utils.h"
      9 #include "xfa/src/fxfa/src/common/xfa_object.h"
     10 #include "xfa/src/fxfa/src/common/xfa_document.h"
     11 #include "xfa/src/fxfa/src/common/xfa_parser.h"
     12 #include "xfa/src/fxfa/src/common/xfa_script.h"
     13 #include "xfa/src/fxfa/src/common/xfa_docdata.h"
     14 #include "xfa/src/fxfa/src/common/xfa_doclayout.h"
     15 #include "xfa/src/fxfa/src/common/xfa_localemgr.h"
     16 #include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
     17 #include "xfa_script_imp.h"
     18 #include "xfa_script_resolveprocessor.h"
     19 #include "xfa_script_nodehelper.h"
     20 CXFA_ScriptContext::CXFA_ScriptContext(CXFA_Document* pDocument)
     21     : m_pDocument(pDocument),
     22       m_hJsContext(nullptr),
     23       m_hJsRuntime(nullptr),
     24       m_hJsClass(nullptr),
     25       m_eScriptType(XFA_SCRIPTLANGTYPE_Unkown),
     26       m_pEventParam(nullptr),
     27       m_pScriptNodeArray(nullptr),
     28       m_pResolveProcessor(nullptr),
     29       m_hFM2JSContext(nullptr),
     30       m_pThisObject(nullptr),
     31       m_dwBuiltInInFlags(0),
     32       m_eRunAtType(XFA_ATTRIBUTEENUM_Client) {
     33   FX_memset(&m_JsGlobalClass, 0, sizeof(FXJSE_CLASS));
     34   FX_memset(&m_JsNormalClass, 0, sizeof(FXJSE_CLASS));
     35 }
     36 CXFA_ScriptContext::~CXFA_ScriptContext() {
     37   FX_POSITION ps = m_mapXFAToHValue.GetStartPosition();
     38   while (ps) {
     39     CXFA_Object* pXFAObj;
     40     FXJSE_HVALUE pValue;
     41     m_mapXFAToHValue.GetNextAssoc(ps, pXFAObj, pValue);
     42     FXJSE_Value_Release(pValue);
     43   }
     44   m_mapXFAToHValue.RemoveAll();
     45   ReleaseVariablesMap();
     46   if (m_hFM2JSContext) {
     47     XFA_FM2JS_ContextRelease(m_hFM2JSContext);
     48     m_hFM2JSContext = NULL;
     49   }
     50   if (m_hJsContext) {
     51     FXJSE_Context_Release(m_hJsContext);
     52     m_hJsContext = NULL;
     53   }
     54   if (m_pResolveProcessor) {
     55     delete m_pResolveProcessor;
     56     m_pResolveProcessor = NULL;
     57   }
     58   m_upObjectArray.RemoveAll();
     59   for (int32_t i = 0; i < m_CacheListArray.GetSize(); i++) {
     60     delete ((CXFA_NodeList*)m_CacheListArray[i]);
     61   }
     62   m_CacheListArray.RemoveAll();
     63   if (m_dwBuiltInInFlags & XFA_JSBUILTIN_HasCount) {
     64     FX_POSITION ps = m_JSBuiltInObjects.GetStartPosition();
     65     while (ps) {
     66       CFX_ByteString bsKey;
     67       void* pValue = NULL;
     68       m_JSBuiltInObjects.GetNextAssoc(ps, bsKey, pValue);
     69       if (pValue) {
     70         FXJSE_Value_Release((FXJSE_HVALUE)pValue);
     71       }
     72     }
     73     m_JSBuiltInObjects.RemoveAll();
     74   }
     75 }
     76 void CXFA_ScriptContext::Initialize(FXJSE_HRUNTIME hRuntime) {
     77   m_hJsRuntime = hRuntime;
     78   DefineJsContext();
     79   DefineJsClass();
     80   m_pResolveProcessor = new CXFA_ResolveProcessor;
     81 }
     82 void CXFA_ScriptContext::Release() {
     83   delete this;
     84 }
     85 FX_BOOL CXFA_ScriptContext::RunScript(XFA_SCRIPTLANGTYPE eScriptType,
     86                                       const CFX_WideStringC& wsScript,
     87                                       FXJSE_HVALUE hRetValue,
     88                                       CXFA_Object* pThisObject) {
     89   CFX_ByteString btScript;
     90   XFA_SCRIPTLANGTYPE eSaveType = m_eScriptType;
     91   m_eScriptType = eScriptType;
     92   if (eScriptType == XFA_SCRIPTLANGTYPE_Formcalc) {
     93     if (!m_hFM2JSContext) {
     94       m_hFM2JSContext = XFA_FM2JS_ContextCreate();
     95       XFA_FM2JS_ContextInitialize(m_hFM2JSContext, m_hJsRuntime, m_hJsContext,
     96                                   m_pDocument);
     97     }
     98     CFX_WideTextBuf wsJavaScript;
     99     CFX_WideString wsErrorInfo;
    100     int32_t iFlags = XFA_FM2JS_Translate(wsScript, wsJavaScript, wsErrorInfo);
    101     if (iFlags) {
    102       FXJSE_Value_SetUndefined(hRetValue);
    103       return FALSE;
    104     }
    105     btScript =
    106         FX_UTF8Encode(wsJavaScript.GetBuffer(), wsJavaScript.GetLength());
    107   } else {
    108     if ((m_dwBuiltInInFlags & XFA_JSBUILTIN_Initialized) == 0) {
    109       m_dwBuiltInInFlags = XFA_JSBUILTIN_Initialized;
    110       FX_POSITION ps = m_JSBuiltInObjects.GetStartPosition();
    111       if (ps) {
    112         FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(m_hJsContext);
    113         while (ps) {
    114           CFX_ByteString bsKey;
    115           void* pValue;
    116           m_JSBuiltInObjects.GetNextAssoc(ps, bsKey, pValue);
    117           FXJSE_HVALUE hProp = FXJSE_Value_Create(m_hJsRuntime);
    118           if (FXJSE_Value_GetObjectProp(hObject, bsKey, hProp)) {
    119             m_JSBuiltInObjects.SetAt(bsKey, hProp);
    120             FXJSE_Value_DeleteObjectProp(hObject, bsKey);
    121             m_dwBuiltInInFlags |= XFA_JSBUILTIN_HasCount;
    122           } else {
    123             m_JSBuiltInObjects.RemoveKey(bsKey);
    124             FXJSE_Value_Release(hProp);
    125           }
    126         }
    127         FXJSE_Value_Release(hObject);
    128       }
    129     }
    130     btScript = FX_UTF8Encode(wsScript.GetPtr(), wsScript.GetLength());
    131   }
    132   CXFA_Object* pOriginalObject = m_pThisObject;
    133   m_pThisObject = pThisObject;
    134   FXJSE_HVALUE pValue = pThisObject ? GetJSValueFromMap(pThisObject) : NULL;
    135   FX_BOOL bRet = FXJSE_ExecuteScript(m_hJsContext, btScript, hRetValue, pValue);
    136   m_pThisObject = pOriginalObject;
    137   m_eScriptType = eSaveType;
    138   return bRet;
    139 }
    140 void CXFA_ScriptContext::GlobalPropertySetter(FXJSE_HOBJECT hObject,
    141                                               const CFX_ByteStringC& szPropName,
    142                                               FXJSE_HVALUE hValue) {
    143   CXFA_Object* lpOrginalNode =
    144       (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    145   CXFA_Document* pDoc = lpOrginalNode->GetDocument();
    146   CXFA_ScriptContext* lpScriptContext =
    147       (CXFA_ScriptContext*)pDoc->GetScriptContext();
    148   CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode);
    149   CFX_WideString wsPropName = CFX_WideString::FromUTF8(
    150       (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
    151   FX_DWORD dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings |
    152                     XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
    153                     XFA_RESOLVENODE_Attributes;
    154   CXFA_Node* pRefNode = (CXFA_Node*)lpScriptContext->GetThisObject();
    155   if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    156     pRefNode = (CXFA_Node*)lpCurNode;
    157   }
    158   if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
    159                                        TRUE)) {
    160     return;
    161   }
    162   if (lpOrginalNode->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    163     if (FXJSE_Value_IsUndefined(hValue)) {
    164       FXJSE_Value_SetObjectOwnProp(hObject, szPropName, hValue);
    165       return;
    166     }
    167   }
    168   IXFA_Notify* pNotify = pDoc->GetNotify();
    169   if (!pNotify) {
    170     return;
    171   }
    172   pNotify->GetDocProvider()->SetGlobalProperty(pNotify->GetHDOC(), szPropName,
    173                                                hValue);
    174 }
    175 FX_BOOL CXFA_ScriptContext::QueryNodeByFlag(CXFA_Node* refNode,
    176                                             const CFX_WideStringC& propname,
    177                                             FXJSE_HVALUE hValue,
    178                                             FX_DWORD dwFlag,
    179                                             FX_BOOL bSetting) {
    180   XFA_RESOLVENODE_RS resolveRs;
    181   int32_t iRet = ResolveObjects(refNode, propname, resolveRs, dwFlag);
    182   FX_BOOL bResult = FALSE;
    183   if (iRet > 0) {
    184     bResult = TRUE;
    185     if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
    186       FXJSE_HVALUE pValue = GetJSValueFromMap(resolveRs.nodes[0]);
    187       FXJSE_Value_Set(hValue, pValue);
    188     } else if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Attribute) {
    189       XFA_LPCSCRIPTATTRIBUTEINFO lpAttributeInfo = resolveRs.pScriptAttribute;
    190       if (lpAttributeInfo) {
    191         (resolveRs.nodes[0]->*(lpAttributeInfo->lpfnCallback))(
    192             hValue, bSetting, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
    193       }
    194     }
    195   }
    196   return bResult;
    197 }
    198 void CXFA_ScriptContext::GlobalPropertyGetter(FXJSE_HOBJECT hObject,
    199                                               const CFX_ByteStringC& szPropName,
    200                                               FXJSE_HVALUE hValue) {
    201   CXFA_Object* pOrginalObject =
    202       (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    203   CXFA_Document* pDoc = pOrginalObject->GetDocument();
    204   CXFA_ScriptContext* lpScriptContext =
    205       (CXFA_ScriptContext*)pDoc->GetScriptContext();
    206   CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(pOrginalObject);
    207   CFX_WideString wsPropName = CFX_WideString::FromUTF8(
    208       (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
    209   if (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Formcalc) {
    210     if (szPropName == FOXIT_XFA_FM2JS_FORMCALC_RUNTIME) {
    211       XFA_FM2JS_GlobalPropertyGetter(lpScriptContext->m_hFM2JSContext, hValue);
    212       return;
    213     }
    214     uint32_t uHashCode =
    215         FX_HashCode_String_GetW(wsPropName, wsPropName.GetLength());
    216     if (uHashCode != XFA_HASHCODE_Layout) {
    217       CXFA_Object* pObject =
    218           lpScriptContext->GetDocument()->GetXFANode(uHashCode);
    219       if (pObject) {
    220         FXJSE_Value_Set(hValue, lpScriptContext->GetJSValueFromMap(pObject));
    221         return;
    222       }
    223     }
    224   }
    225   FX_DWORD dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
    226                     XFA_RESOLVENODE_Attributes;
    227   CXFA_Node* pRefNode = (CXFA_Node*)lpScriptContext->GetThisObject();
    228   if (pOrginalObject->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    229     pRefNode = (CXFA_Node*)lpCurNode;
    230   }
    231   if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
    232                                        FALSE)) {
    233     return;
    234   }
    235   dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings;
    236   if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName, hValue, dwFlag,
    237                                        FALSE)) {
    238     return;
    239   }
    240   CXFA_Object* pScriptObject =
    241       lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
    242   if (pScriptObject &&
    243       lpScriptContext->QueryVariableHValue((CXFA_Node*)pScriptObject,
    244                                            szPropName, hValue, TRUE)) {
    245     return;
    246   }
    247   if (lpScriptContext->QueryBuiltinHValue(szPropName, hValue)) {
    248     return;
    249   }
    250   IXFA_Notify* pNotify = pDoc->GetNotify();
    251   if (!pNotify) {
    252     return;
    253   }
    254   pNotify->GetDocProvider()->GetGlobalProperty(pNotify->GetHDOC(), szPropName,
    255                                                hValue);
    256 }
    257 void CXFA_ScriptContext::NormalPropertyGetter(FXJSE_HOBJECT hObject,
    258                                               const CFX_ByteStringC& szPropName,
    259                                               FXJSE_HVALUE hValue) {
    260   CXFA_Object* pOrginalObject =
    261       (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    262   if (pOrginalObject == NULL) {
    263     FXJSE_Value_SetUndefined(hValue);
    264     return;
    265   }
    266   CFX_WideString wsPropName = CFX_WideString::FromUTF8(
    267       (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
    268   CXFA_ScriptContext* lpScriptContext =
    269       (CXFA_ScriptContext*)pOrginalObject->GetDocument()->GetScriptContext();
    270   CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOrginalObject);
    271   if (wsPropName == FX_WSTRC(L"xfa")) {
    272     FXJSE_HVALUE pValue = lpScriptContext->GetJSValueFromMap(
    273         lpScriptContext->GetDocument()->GetRoot());
    274     FXJSE_Value_Set(hValue, pValue);
    275     return;
    276   }
    277   FX_DWORD dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
    278                     XFA_RESOLVENODE_Attributes;
    279   FX_BOOL bRet = lpScriptContext->QueryNodeByFlag(
    280       (CXFA_Node*)pObject, wsPropName, hValue, dwFlag, FALSE);
    281   if (bRet) {
    282     return;
    283   }
    284   if (pObject == lpScriptContext->GetThisObject() ||
    285       (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Javascript &&
    286        !lpScriptContext->IsStrictScopeInJavaScript())) {
    287     dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings;
    288     bRet = lpScriptContext->QueryNodeByFlag((CXFA_Node*)pObject, wsPropName,
    289                                             hValue, dwFlag, FALSE);
    290   }
    291   if (bRet) {
    292     return;
    293   }
    294   CXFA_Object* pScriptObject =
    295       lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
    296   if (pScriptObject) {
    297     bRet = lpScriptContext->QueryVariableHValue((CXFA_Node*)pScriptObject,
    298                                                 szPropName, hValue, TRUE);
    299   }
    300   if (!bRet) {
    301     FXJSE_Value_SetUndefined(hValue);
    302   }
    303 }
    304 void CXFA_ScriptContext::NormalPropertySetter(FXJSE_HOBJECT hObject,
    305                                               const CFX_ByteStringC& szPropName,
    306                                               FXJSE_HVALUE hValue) {
    307   CXFA_Object* pOrginalObject =
    308       (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    309   if (pOrginalObject == NULL) {
    310     return;
    311   }
    312   CXFA_ScriptContext* lpScriptContext =
    313       (CXFA_ScriptContext*)pOrginalObject->GetDocument()->GetScriptContext();
    314   CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOrginalObject);
    315   CFX_WideString wsPropName = CFX_WideString::FromUTF8(
    316       (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
    317   XFA_LPCSCRIPTATTRIBUTEINFO lpAttributeInfo =
    318       XFA_GetScriptAttributeByName(pObject->GetClassID(), wsPropName);
    319   if (lpAttributeInfo) {
    320     (pObject->*(lpAttributeInfo->lpfnCallback))(
    321         hValue, TRUE, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
    322   } else {
    323     if (pObject->IsNode()) {
    324       if (wsPropName.GetAt(0) == '#') {
    325         wsPropName = wsPropName.Right(wsPropName.GetLength() - 1);
    326       }
    327       CXFA_Node* pNode = (CXFA_Node*)pObject;
    328       CXFA_Node* pPropOrChild = NULL;
    329       XFA_LPCELEMENTINFO lpElementInfo = XFA_GetElementByName(wsPropName);
    330       if (lpElementInfo) {
    331         pPropOrChild = pNode->GetProperty(0, lpElementInfo->eName);
    332       } else {
    333         pPropOrChild = pNode->GetFirstChildByName(wsPropName);
    334       }
    335       if (pPropOrChild) {
    336         CFX_WideString wsDefaultName = FX_WSTRC(L"{default}");
    337         XFA_LPCSCRIPTATTRIBUTEINFO lpAttributeInfo =
    338             XFA_GetScriptAttributeByName(pPropOrChild->GetClassID(),
    339                                          wsDefaultName);
    340         if (lpAttributeInfo) {
    341           (pPropOrChild->*(lpAttributeInfo->lpfnCallback))(
    342               hValue, TRUE, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute);
    343           return;
    344         }
    345       }
    346     }
    347     CXFA_Object* pScriptObject =
    348         lpScriptContext->GetVariablesThis(pOrginalObject, TRUE);
    349     if (pScriptObject) {
    350       lpScriptContext->QueryVariableHValue((CXFA_Node*)pScriptObject,
    351                                            szPropName, hValue, FALSE);
    352     }
    353   }
    354 }
    355 int32_t CXFA_ScriptContext::NormalPropTypeGetter(
    356     FXJSE_HOBJECT hObject,
    357     const CFX_ByteStringC& szPropName,
    358     FX_BOOL bQueryIn) {
    359   CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    360   if (pObject == NULL) {
    361     return FXJSE_ClassPropType_None;
    362   }
    363   CXFA_ScriptContext* lpScriptContext =
    364       (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
    365   pObject = lpScriptContext->GetVariablesThis(pObject);
    366   XFA_ELEMENT objElement = pObject->GetClassID();
    367   CFX_WideString wsPropName = CFX_WideString::FromUTF8(
    368       (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
    369   if (XFA_GetMethodByName(objElement, wsPropName)) {
    370     return FXJSE_ClassPropType_Method;
    371   }
    372   if (bQueryIn && !XFA_GetScriptAttributeByName(objElement, wsPropName)) {
    373     return FXJSE_ClassPropType_None;
    374   }
    375   return FXJSE_ClassPropType_Property;
    376 }
    377 int32_t CXFA_ScriptContext::GlobalPropTypeGetter(
    378     FXJSE_HOBJECT hObject,
    379     const CFX_ByteStringC& szPropName,
    380     FX_BOOL bQueryIn) {
    381   CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    382   if (pObject == NULL) {
    383     return FXJSE_ClassPropType_None;
    384   }
    385   CXFA_ScriptContext* lpScriptContext =
    386       (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
    387   pObject = lpScriptContext->GetVariablesThis(pObject);
    388   XFA_ELEMENT objElement = pObject->GetClassID();
    389   CFX_WideString wsPropName = CFX_WideString::FromUTF8(
    390       (const FX_CHAR*)szPropName.GetPtr(), szPropName.GetLength());
    391   if (XFA_GetMethodByName(objElement, wsPropName)) {
    392     return FXJSE_ClassPropType_Method;
    393   }
    394   return FXJSE_ClassPropType_Property;
    395 }
    396 void CXFA_ScriptContext::NormalMethodCall(FXJSE_HOBJECT hThis,
    397                                           const CFX_ByteStringC& szFuncName,
    398                                           CFXJSE_Arguments& args) {
    399   CXFA_Object* pObject = (CXFA_Object*)FXJSE_Value_ToObject(hThis, NULL);
    400   if (pObject == NULL) {
    401     return;
    402   }
    403   CXFA_ScriptContext* lpScriptContext =
    404       (CXFA_ScriptContext*)pObject->GetDocument()->GetScriptContext();
    405   pObject = lpScriptContext->GetVariablesThis(pObject);
    406   CFX_WideString wsFunName = CFX_WideString::FromUTF8(
    407       (const FX_CHAR*)szFuncName.GetPtr(), szFuncName.GetLength());
    408   XFA_LPCMETHODINFO lpMethodInfo =
    409       XFA_GetMethodByName(pObject->GetClassID(), wsFunName);
    410   if (NULL == lpMethodInfo) {
    411     return;
    412   }
    413   (pObject->*(lpMethodInfo->lpfnCallback))(&args);
    414 }
    415 FX_BOOL CXFA_ScriptContext::IsStrictScopeInJavaScript() {
    416   return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping);
    417 }
    418 XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() {
    419   return m_eScriptType;
    420 }
    421 void CXFA_ScriptContext::DefineJsContext() {
    422   m_JsGlobalClass.constructor = NULL;
    423   m_JsGlobalClass.name = "Root";
    424   m_JsGlobalClass.propNum = 0;
    425   m_JsGlobalClass.properties = NULL;
    426   m_JsGlobalClass.methNum = 0;
    427   m_JsGlobalClass.methods = NULL;
    428   m_JsGlobalClass.dynPropGetter = CXFA_ScriptContext::GlobalPropertyGetter;
    429   m_JsGlobalClass.dynPropSetter = CXFA_ScriptContext::GlobalPropertySetter;
    430   m_JsGlobalClass.dynPropTypeGetter = CXFA_ScriptContext::GlobalPropTypeGetter;
    431   m_JsGlobalClass.dynPropDeleter = NULL;
    432   m_JsGlobalClass.dynMethodCall = CXFA_ScriptContext::NormalMethodCall;
    433   m_hJsContext = FXJSE_Context_Create(m_hJsRuntime, &m_JsGlobalClass,
    434                                       m_pDocument->GetRoot());
    435   FXJSE_Context_EnableCompatibleMode(
    436       m_hJsContext, FXJSE_COMPATIBLEMODEFLAG_CONSTRUCTOREXTRAMETHODS);
    437 }
    438 FXJSE_HCONTEXT CXFA_ScriptContext::CreateVariablesContext(
    439     CXFA_Node* pScriptNode,
    440     CXFA_Node* pSubform) {
    441   if (pScriptNode == NULL || pSubform == NULL) {
    442     return NULL;
    443   }
    444   if (m_mapVariableToHValue.GetCount() == 0) {
    445     m_JsGlobalVariablesClass.constructor = NULL;
    446     m_JsGlobalVariablesClass.name = "XFAScriptObject";
    447     m_JsGlobalVariablesClass.propNum = 0;
    448     m_JsGlobalVariablesClass.properties = NULL;
    449     m_JsGlobalVariablesClass.methNum = 0;
    450     m_JsGlobalVariablesClass.methods = NULL;
    451     m_JsGlobalVariablesClass.dynPropGetter =
    452         CXFA_ScriptContext::GlobalPropertyGetter;
    453     m_JsGlobalVariablesClass.dynPropSetter =
    454         CXFA_ScriptContext::GlobalPropertySetter;
    455     m_JsGlobalVariablesClass.dynPropTypeGetter =
    456         CXFA_ScriptContext::NormalPropTypeGetter;
    457     m_JsGlobalVariablesClass.dynPropDeleter = NULL;
    458     m_JsGlobalVariablesClass.dynMethodCall =
    459         CXFA_ScriptContext::NormalMethodCall;
    460   }
    461   CXFA_ThisProxy* lpVariableNode = new CXFA_ThisProxy(pSubform, pScriptNode);
    462   FXJSE_HCONTEXT hVariablesContext = FXJSE_Context_Create(
    463       m_hJsRuntime, &m_JsGlobalVariablesClass, (CXFA_Object*)lpVariableNode);
    464   FXJSE_Context_EnableCompatibleMode(
    465       hVariablesContext, FXJSE_COMPATIBLEMODEFLAG_CONSTRUCTOREXTRAMETHODS);
    466   m_mapVariableToHValue.SetAt(pScriptNode, hVariablesContext);
    467   return hVariablesContext;
    468 }
    469 CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject,
    470                                                   FX_BOOL bScriptNode) {
    471   if (pObject->GetObjectType() == XFA_OBJECTTYPE_VariablesThis) {
    472     return bScriptNode ? ((CXFA_ThisProxy*)pObject)->GetScriptNode()
    473                        : ((CXFA_ThisProxy*)pObject)->GetThisNode();
    474   }
    475   return pObject;
    476 }
    477 FX_BOOL CXFA_ScriptContext::RunVariablesScript(CXFA_Node* pScriptNode) {
    478   if (pScriptNode == NULL) {
    479     return FALSE;
    480   }
    481   if (pScriptNode->GetClassID() == XFA_ELEMENT_Script) {
    482     CXFA_Node* pParent = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent);
    483     if (!pParent || pParent->GetClassID() != XFA_ELEMENT_Variables) {
    484       return FALSE;
    485     }
    486     if (m_mapVariableToHValue.GetValueAt(pScriptNode)) {
    487       return TRUE;
    488     }
    489     CXFA_Node* pTextNode = pScriptNode->GetNodeItem(XFA_NODEITEM_FirstChild);
    490     if (!pTextNode) {
    491       return FALSE;
    492     }
    493     CFX_WideStringC wsScript;
    494     if (!pTextNode->TryCData(XFA_ATTRIBUTE_Value, wsScript)) {
    495       return FALSE;
    496     }
    497     CFX_ByteString btScript =
    498         FX_UTF8Encode(wsScript.GetPtr(), wsScript.GetLength());
    499     FXJSE_HVALUE hRetValue = FXJSE_Value_Create(m_hJsRuntime);
    500     CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent);
    501     FXJSE_HCONTEXT hVariablesContext =
    502         CreateVariablesContext(pScriptNode, pThisObject);
    503     CXFA_Object* pOriginalObject = m_pThisObject;
    504     m_pThisObject = pThisObject;
    505     FX_BOOL bRet = FXJSE_ExecuteScript(hVariablesContext, btScript, hRetValue);
    506     m_pThisObject = pOriginalObject;
    507     FXJSE_Value_Release(hRetValue);
    508     return bRet;
    509   }
    510   return TRUE;
    511 }
    512 FX_BOOL CXFA_ScriptContext::QueryVariableHValue(
    513     CXFA_Node* pScriptNode,
    514     const CFX_ByteStringC& szPropName,
    515     FXJSE_HVALUE hValue,
    516     FX_BOOL bGetter) {
    517   if (pScriptNode->GetClassID() != XFA_ELEMENT_Script) {
    518     return FALSE;
    519   }
    520   CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent);
    521   if (!variablesNode || variablesNode->GetClassID() != XFA_ELEMENT_Variables) {
    522     return FALSE;
    523   }
    524   FX_BOOL bRes = FALSE;
    525   void* lpVariables = m_mapVariableToHValue.GetValueAt(pScriptNode);
    526   if (lpVariables) {
    527     FXJSE_HCONTEXT hVariableContext = (FXJSE_HCONTEXT)lpVariables;
    528     FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(hVariableContext);
    529     FXJSE_HVALUE hVariableValue = FXJSE_Value_Create(m_hJsRuntime);
    530     if (!bGetter) {
    531       FXJSE_Value_SetObjectOwnProp(hObject, szPropName, hValue);
    532       bRes = TRUE;
    533     } else if (FXJSE_Value_ObjectHasOwnProp(hObject, szPropName, FALSE)) {
    534       FXJSE_Value_GetObjectProp(hObject, szPropName, hVariableValue);
    535       if (FXJSE_Value_IsFunction(hVariableValue)) {
    536         FXJSE_Value_SetFunctionBind(hValue, hVariableValue, hObject);
    537       } else if (bGetter) {
    538         FXJSE_Value_Set(hValue, hVariableValue);
    539       } else {
    540         FXJSE_Value_Set(hVariableValue, hValue);
    541       }
    542       bRes = TRUE;
    543     }
    544     FXJSE_Value_Release(hVariableValue);
    545     FXJSE_Value_Release(hObject);
    546   }
    547   return bRes;
    548 }
    549 FX_BOOL CXFA_ScriptContext::QueryBuiltinHValue(
    550     const CFX_ByteStringC& szPropName,
    551     FXJSE_HVALUE hValue) {
    552   void* pBuiltin = NULL;
    553   if ((m_dwBuiltInInFlags & XFA_JSBUILTIN_HasCount) &&
    554       m_JSBuiltInObjects.Lookup(szPropName, pBuiltin)) {
    555     FXJSE_Value_Set(hValue, (FXJSE_HVALUE)pBuiltin);
    556     return TRUE;
    557   }
    558   return FALSE;
    559 }
    560 void CXFA_ScriptContext::ReleaseVariablesMap() {
    561   FX_POSITION ps = m_mapVariableToHValue.GetStartPosition();
    562   while (ps) {
    563     CXFA_Object* pScriptNode;
    564     FXJSE_HCONTEXT hVariableContext;
    565     m_mapVariableToHValue.GetNextAssoc(ps, pScriptNode, hVariableContext);
    566     FXJSE_HVALUE hObject = FXJSE_Context_GetGlobalObject(hVariableContext);
    567     CXFA_Object* lpCurNode = (CXFA_Object*)FXJSE_Value_ToObject(hObject, NULL);
    568     if (lpCurNode) {
    569       delete (CXFA_ThisProxy*)lpCurNode;
    570       lpCurNode = NULL;
    571     }
    572     FXJSE_Value_Release(hObject);
    573     FXJSE_Context_Release(hVariableContext);
    574     hVariableContext = NULL;
    575   }
    576   m_mapVariableToHValue.RemoveAll();
    577 }
    578 void CXFA_ScriptContext::DefineJsClass() {
    579   m_JsNormalClass.constructor = NULL;
    580   m_JsNormalClass.name = "XFAObject";
    581   m_JsNormalClass.propNum = 0;
    582   m_JsNormalClass.properties = NULL;
    583   m_JsNormalClass.methNum = 0;
    584   m_JsNormalClass.methods = NULL;
    585   m_JsNormalClass.dynPropGetter = CXFA_ScriptContext::NormalPropertyGetter;
    586   m_JsNormalClass.dynPropSetter = CXFA_ScriptContext::NormalPropertySetter;
    587   m_JsNormalClass.dynPropTypeGetter = CXFA_ScriptContext::NormalPropTypeGetter;
    588   m_JsNormalClass.dynPropDeleter = NULL;
    589   m_JsNormalClass.dynMethodCall = CXFA_ScriptContext::NormalMethodCall;
    590   m_hJsClass = FXJSE_DefineClass(m_hJsContext, &m_JsNormalClass);
    591 }
    592 FXJSE_HCLASS CXFA_ScriptContext::GetJseNormalClass() {
    593   return m_hJsClass;
    594 }
    595 void CXFA_ScriptContext::AddJSBuiltinObject(
    596     XFA_LPCJSBUILTININFO pBuitinObject) {
    597   if (m_dwBuiltInInFlags & XFA_JSBUILTIN_Initialized) {
    598     return;
    599   }
    600   m_JSBuiltInObjects.SetAt(pBuitinObject->pName, (void*)pBuitinObject);
    601 }
    602 int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode,
    603                                            const CFX_WideStringC& wsExpression,
    604                                            XFA_RESOLVENODE_RS& resolveNodeRS,
    605                                            FX_DWORD dwStyles,
    606                                            CXFA_Node* bindNode) {
    607   if (wsExpression.IsEmpty()) {
    608     return 0;
    609   }
    610   if (m_eScriptType != XFA_SCRIPTLANGTYPE_Formcalc ||
    611       (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) {
    612     m_upObjectArray.RemoveAll();
    613   }
    614   if (refNode &&
    615       (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings)) &&
    616       refNode->IsNode()) {
    617     m_upObjectArray.Add((CXFA_Node*)refNode);
    618   }
    619   FX_BOOL bNextCreate = FALSE;
    620   if (dwStyles & XFA_RESOLVENODE_CreateNode) {
    621     m_pResolveProcessor->GetNodeHelper()->XFA_SetCreateNodeType(bindNode);
    622   }
    623   m_pResolveProcessor->GetNodeHelper()->m_pCreateParent = NULL;
    624   m_pResolveProcessor->GetNodeHelper()->m_iCurAllStart = -1;
    625   CXFA_ResolveNodesData rndFind;
    626   int32_t nStart = 0;
    627   int32_t nLevel = 0;
    628   int32_t nRet = -1;
    629   rndFind.m_pSC = this;
    630   CXFA_ObjArray findNodes;
    631   if (refNode != NULL) {
    632     findNodes.Add(refNode);
    633   } else {
    634     findNodes.Add(m_pDocument->GetRoot());
    635   }
    636   int32_t nNodes = 0;
    637   while (TRUE) {
    638     nNodes = findNodes.GetSize();
    639     int32_t i = 0;
    640     rndFind.m_dwStyles = dwStyles;
    641     m_pResolveProcessor->m_iCurStart = nStart;
    642     nStart = m_pResolveProcessor->XFA_ResolveNodes_GetFilter(wsExpression,
    643                                                              nStart, rndFind);
    644     if (nStart < 1) {
    645       if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) {
    646         CXFA_Node* pDataNode = NULL;
    647         nStart = m_pResolveProcessor->GetNodeHelper()->m_iCurAllStart;
    648         if (nStart != -1) {
    649           pDataNode = m_pDocument->GetNotBindNode(findNodes);
    650           if (pDataNode) {
    651             findNodes.RemoveAll();
    652             findNodes.Add(pDataNode);
    653             break;
    654           }
    655         } else {
    656           pDataNode = (CXFA_Node*)findNodes[0];
    657           findNodes.RemoveAll();
    658           findNodes.Add(pDataNode);
    659           break;
    660         }
    661         dwStyles |= XFA_RESOLVENODE_Bind;
    662         findNodes.RemoveAll();
    663         findNodes.Add(m_pResolveProcessor->GetNodeHelper()->m_pAllStartParent);
    664         continue;
    665       } else {
    666         break;
    667       }
    668     }
    669     if (bNextCreate) {
    670       FX_BOOL bCreate =
    671           m_pResolveProcessor->GetNodeHelper()->XFA_ResolveNodes_CreateNode(
    672               rndFind.m_wsName, rndFind.m_wsCondition,
    673               nStart == wsExpression.GetLength(), this);
    674       if (bCreate) {
    675         continue;
    676       } else {
    677         break;
    678       }
    679     }
    680     CXFA_ObjArray retNodes;
    681     while (i < nNodes) {
    682       FX_BOOL bDataBind = FALSE;
    683       if (((dwStyles & XFA_RESOLVENODE_Bind) ||
    684            (dwStyles & XFA_RESOLVENODE_CreateNode)) &&
    685           nNodes > 1) {
    686         CXFA_ResolveNodesData rndBind;
    687         m_pResolveProcessor->XFA_ResolveNodes_GetFilter(wsExpression, nStart,
    688                                                         rndBind);
    689         m_pResolveProcessor->XFA_ResolveNode_SetIndexDataBind(
    690             rndBind.m_wsCondition, i, nNodes);
    691         bDataBind = TRUE;
    692       }
    693       rndFind.m_CurNode = findNodes[i++];
    694       rndFind.m_nLevel = nLevel;
    695       rndFind.m_dwFlag = XFA_RESOVENODE_RSTYPE_Nodes;
    696       nRet = m_pResolveProcessor->XFA_ResolveNodes(rndFind);
    697       if (nRet < 1) {
    698         continue;
    699       }
    700       if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute &&
    701           rndFind.m_pScriptAttribute && nStart < wsExpression.GetLength()) {
    702         FXJSE_HVALUE hValue = FXJSE_Value_Create(m_hJsRuntime);
    703         (rndFind.m_Nodes[0]->*(rndFind.m_pScriptAttribute->lpfnCallback))(
    704             hValue, FALSE,
    705             (XFA_ATTRIBUTE)rndFind.m_pScriptAttribute->eAttribute);
    706         rndFind.m_Nodes.SetAt(0,
    707                               (CXFA_Object*)FXJSE_Value_ToObject(hValue, NULL));
    708         FXJSE_Value_Release(hValue);
    709       }
    710       int32_t iSize = m_upObjectArray.GetSize();
    711       if (iSize) {
    712         m_upObjectArray.RemoveAt(iSize - 1);
    713       }
    714       retNodes.Append(rndFind.m_Nodes);
    715       rndFind.m_Nodes.RemoveAll();
    716       if (bDataBind) {
    717         break;
    718       }
    719     }
    720     findNodes.RemoveAll();
    721     nNodes = retNodes.GetSize();
    722     if (nNodes < 1) {
    723       if (dwStyles & XFA_RESOLVENODE_CreateNode) {
    724         bNextCreate = TRUE;
    725         if (m_pResolveProcessor->GetNodeHelper()->m_pCreateParent == NULL) {
    726           m_pResolveProcessor->GetNodeHelper()->m_pCreateParent =
    727               (CXFA_Node*)rndFind.m_CurNode;
    728           m_pResolveProcessor->GetNodeHelper()->m_iCreateCount = 1;
    729         }
    730         FX_BOOL bCreate =
    731             m_pResolveProcessor->GetNodeHelper()->XFA_ResolveNodes_CreateNode(
    732                 rndFind.m_wsName, rndFind.m_wsCondition,
    733                 nStart == wsExpression.GetLength(), this);
    734         if (bCreate) {
    735           continue;
    736         } else {
    737           break;
    738         }
    739       } else {
    740         break;
    741       }
    742     }
    743     findNodes.Copy(retNodes);
    744     rndFind.m_Nodes.RemoveAll();
    745     if (nLevel == 0) {
    746       dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
    747     }
    748     nLevel++;
    749   }
    750   if (!bNextCreate) {
    751     resolveNodeRS.dwFlags = rndFind.m_dwFlag;
    752     if (nNodes > 0) {
    753       resolveNodeRS.nodes.Append(findNodes);
    754     }
    755     if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute) {
    756       resolveNodeRS.pScriptAttribute = rndFind.m_pScriptAttribute;
    757       return 1;
    758     }
    759   }
    760   if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind |
    761                   XFA_RESOLVENODE_BindNew)) {
    762     m_pResolveProcessor->XFA_ResolveNode_SetResultCreateNode(
    763         resolveNodeRS, rndFind.m_wsCondition);
    764     if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) {
    765       resolveNodeRS.dwFlags = XFA_RESOVENODE_RSTYPE_ExistNodes;
    766     }
    767     return resolveNodeRS.nodes.GetSize();
    768   }
    769   return nNodes;
    770 }
    771 FXJSE_HVALUE CXFA_ScriptContext::GetJSValueFromMap(CXFA_Object* pObject) {
    772   if (!pObject) {
    773     return NULL;
    774   }
    775   if (pObject->IsNode()) {
    776     RunVariablesScript((CXFA_Node*)pObject);
    777   }
    778   void* pValue = m_mapXFAToHValue.GetValueAt(pObject);
    779   if (pValue == NULL) {
    780     FXJSE_HVALUE jsHvalue = FXJSE_Value_Create(m_hJsRuntime);
    781     FXJSE_Value_SetObject(jsHvalue, pObject, m_hJsClass);
    782     m_mapXFAToHValue.SetAt(pObject, jsHvalue);
    783     pValue = jsHvalue;
    784   }
    785   return (FXJSE_HVALUE)pValue;
    786 }
    787 int32_t CXFA_ScriptContext::GetIndexByName(CXFA_Node* refNode) {
    788   CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
    789   return lpNodeHelper->XFA_GetIndex(refNode, XFA_LOGIC_Transparent,
    790                                     lpNodeHelper->XFA_NodeIsProperty(refNode),
    791                                     FALSE);
    792 }
    793 int32_t CXFA_ScriptContext::GetIndexByClassName(CXFA_Node* refNode) {
    794   CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
    795   return lpNodeHelper->XFA_GetIndex(refNode, XFA_LOGIC_Transparent,
    796                                     lpNodeHelper->XFA_NodeIsProperty(refNode),
    797                                     TRUE);
    798 }
    799 void CXFA_ScriptContext::GetSomExpression(CXFA_Node* refNode,
    800                                           CFX_WideString& wsExpression) {
    801   CXFA_NodeHelper* lpNodeHelper = m_pResolveProcessor->GetNodeHelper();
    802   lpNodeHelper->XFA_GetNameExpression(refNode, wsExpression, TRUE,
    803                                       XFA_LOGIC_Transparent);
    804 }
    805 void CXFA_ScriptContext::SetNodesOfRunScript(CXFA_NodeArray* pArray) {
    806   m_pScriptNodeArray = pArray;
    807 }
    808 void CXFA_ScriptContext::AddNodesOfRunScript(const CXFA_NodeArray& nodes) {
    809   if (!m_pScriptNodeArray) {
    810     return;
    811   }
    812   if (nodes.GetSize() > 0) {
    813     m_pScriptNodeArray->Copy(nodes);
    814   }
    815 }
    816 void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) {
    817   if (!m_pScriptNodeArray) {
    818     return;
    819   }
    820   if (m_pScriptNodeArray->Find(pNode) == -1) {
    821     m_pScriptNodeArray->Add(pNode);
    822   }
    823 }
    824 IXFA_ScriptContext* XFA_ScriptContext_Create(CXFA_Document* pDocument) {
    825   return new CXFA_ScriptContext(pDocument);
    826 }
    827 static const XFA_JSBUILTININFO gs_JSBUILTINData[] = {
    828     {0x8108b9a9, "Number"},
    829     {0xe07e3fbe, "Date"},
    830 };
    831 const int32_t g_iJSBuiltinCount =
    832     sizeof(XFA_JSBUILTININFO) / sizeof(XFA_JSBUILTININFO);
    833 XFA_LPCJSBUILTININFO XFA_GetJSBuiltinByHash(uint32_t uHashCode) {
    834   int32_t iStart = 0, iEnd = g_iJSBuiltinCount - 1, iMid;
    835   do {
    836     iMid = (iStart + iEnd) / 2;
    837     XFA_LPCJSBUILTININFO pInfo = gs_JSBUILTINData + iMid;
    838     if (uHashCode == pInfo->uUnicodeHash) {
    839       return pInfo;
    840     } else if (uHashCode < pInfo->uUnicodeHash) {
    841       iEnd = iMid - 1;
    842     } else {
    843       iStart = iMid + 1;
    844     }
    845   } while (iStart <= iEnd);
    846   return NULL;
    847 }
    848