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