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/fxfa/parser/cxfa_scriptcontext.h" 8 9#include <utility> 10 11#include "core/fxcrt/fx_ext.h" 12#include "fxjs/cfxjse_arguments.h" 13#include "fxjs/cfxjse_class.h" 14#include "fxjs/cfxjse_value.h" 15#include "third_party/base/ptr_util.h" 16#include "xfa/fxfa/app/xfa_ffnotify.h" 17#include "xfa/fxfa/cxfa_eventparam.h" 18#include "xfa/fxfa/parser/cxfa_document.h" 19#include "xfa/fxfa/parser/cxfa_nodehelper.h" 20#include "xfa/fxfa/parser/cxfa_resolveprocessor.h" 21#include "xfa/fxfa/parser/xfa_basic_data.h" 22#include "xfa/fxfa/parser/xfa_localemgr.h" 23#include "xfa/fxfa/parser/xfa_object.h" 24#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" 25#include "xfa/fxfa/parser/xfa_utils.h" 26 27namespace { 28 29const FXJSE_CLASS_DESCRIPTOR GlobalClassDescriptor = { 30 "Root", // name 31 nullptr, // constructor 32 nullptr, // properties 33 nullptr, // methods 34 0, // property count 35 0, // method count 36 CXFA_ScriptContext::GlobalPropTypeGetter, 37 CXFA_ScriptContext::GlobalPropertyGetter, 38 CXFA_ScriptContext::GlobalPropertySetter, 39 nullptr, // property deleter 40 CXFA_ScriptContext::NormalMethodCall, 41}; 42 43const FXJSE_CLASS_DESCRIPTOR NormalClassDescriptor = { 44 "XFAObject", // name 45 nullptr, // constructor 46 nullptr, // properties 47 nullptr, // methods 48 0, // property count 49 0, // method count 50 CXFA_ScriptContext::NormalPropTypeGetter, 51 CXFA_ScriptContext::NormalPropertyGetter, 52 CXFA_ScriptContext::NormalPropertySetter, 53 nullptr, // property deleter 54 CXFA_ScriptContext::NormalMethodCall, 55}; 56 57const FXJSE_CLASS_DESCRIPTOR VariablesClassDescriptor = { 58 "XFAScriptObject", // name 59 nullptr, // constructor 60 nullptr, // properties 61 nullptr, // methods 62 0, // property count 63 0, // method count 64 CXFA_ScriptContext::NormalPropTypeGetter, 65 CXFA_ScriptContext::GlobalPropertyGetter, 66 CXFA_ScriptContext::GlobalPropertySetter, 67 nullptr, // property deleter 68 CXFA_ScriptContext::NormalMethodCall, 69}; 70 71const char kFormCalcRuntime[] = "foxit_xfa_formcalc_runtime"; 72 73CXFA_ThisProxy* ToThisProxy(CFXJSE_Value* pValue, CFXJSE_Class* pClass) { 74 return static_cast<CXFA_ThisProxy*>(pValue->ToHostObject(pClass)); 75} 76 77const XFA_METHODINFO* GetMethodByName(XFA_Element eElement, 78 const CFX_WideStringC& wsMethodName) { 79 if (wsMethodName.IsEmpty()) 80 return nullptr; 81 82 int32_t iElementIndex = static_cast<int32_t>(eElement); 83 while (iElementIndex >= 0 && iElementIndex < g_iScriptIndexCount) { 84 const XFA_SCRIPTHIERARCHY* scriptIndex = g_XFAScriptIndex + iElementIndex; 85 int32_t icount = scriptIndex->wMethodCount; 86 if (icount == 0) { 87 iElementIndex = scriptIndex->wParentIndex; 88 continue; 89 } 90 uint32_t uHash = FX_HashCode_GetW(wsMethodName, false); 91 int32_t iStart = scriptIndex->wMethodStart; 92 // TODO(dsinclair): Switch to std::lower_bound. 93 int32_t iEnd = iStart + icount - 1; 94 do { 95 int32_t iMid = (iStart + iEnd) / 2; 96 const XFA_METHODINFO* pInfo = g_SomMethodData + iMid; 97 if (uHash == pInfo->uHash) 98 return pInfo; 99 if (uHash < pInfo->uHash) 100 iEnd = iMid - 1; 101 else 102 iStart = iMid + 1; 103 } while (iStart <= iEnd); 104 iElementIndex = scriptIndex->wParentIndex; 105 } 106 return nullptr; 107} 108 109} // namespace 110 111// static. 112CXFA_Object* CXFA_ScriptContext::ToObject(CFXJSE_Value* pValue, 113 CFXJSE_Class* pClass) { 114 return static_cast<CXFA_Object*>(pValue->ToHostObject(pClass)); 115} 116 117CXFA_ScriptContext::CXFA_ScriptContext(CXFA_Document* pDocument) 118 : m_pDocument(pDocument), 119 m_pIsolate(nullptr), 120 m_pJsClass(nullptr), 121 m_eScriptType(XFA_SCRIPTLANGTYPE_Unkown), 122 m_pScriptNodeArray(nullptr), 123 m_pThisObject(nullptr), 124 m_dwBuiltInInFlags(0), 125 m_eRunAtType(XFA_ATTRIBUTEENUM_Client) {} 126 127CXFA_ScriptContext::~CXFA_ScriptContext() { 128 for (const auto& pair : m_mapVariableToContext) { 129 CFXJSE_Context* pVariableContext = pair.second; 130 delete ToThisProxy(pVariableContext->GetGlobalObject().get(), nullptr); 131 delete pVariableContext; 132 } 133 m_mapVariableToContext.clear(); 134 m_upObjectArray.RemoveAll(); 135} 136 137void CXFA_ScriptContext::Initialize(v8::Isolate* pIsolate) { 138 m_pIsolate = pIsolate; 139 DefineJsContext(); 140 DefineJsClass(); 141 m_ResolveProcessor = pdfium::MakeUnique<CXFA_ResolveProcessor>(); 142} 143 144bool CXFA_ScriptContext::RunScript(XFA_SCRIPTLANGTYPE eScriptType, 145 const CFX_WideStringC& wsScript, 146 CFXJSE_Value* hRetValue, 147 CXFA_Object* pThisObject) { 148 CFX_ByteString btScript; 149 XFA_SCRIPTLANGTYPE eSaveType = m_eScriptType; 150 m_eScriptType = eScriptType; 151 if (eScriptType == XFA_SCRIPTLANGTYPE_Formcalc) { 152 if (!m_FM2JSContext) { 153 m_FM2JSContext.reset( 154 new CXFA_FM2JSContext(m_pIsolate, m_JsContext.get(), m_pDocument)); 155 } 156 CFX_WideTextBuf wsJavaScript; 157 CFX_WideString wsErrorInfo; 158 int32_t iFlags = 159 CXFA_FM2JSContext::Translate(wsScript, wsJavaScript, wsErrorInfo); 160 if (iFlags) { 161 hRetValue->SetUndefined(); 162 return false; 163 } 164 btScript = FX_UTF8Encode(wsJavaScript.AsStringC()); 165 } else { 166 btScript = FX_UTF8Encode(wsScript); 167 } 168 CXFA_Object* pOriginalObject = m_pThisObject; 169 m_pThisObject = pThisObject; 170 CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : nullptr; 171 bool bRet = m_JsContext->ExecuteScript(btScript.c_str(), hRetValue, pValue); 172 m_pThisObject = pOriginalObject; 173 m_eScriptType = eSaveType; 174 return bRet; 175} 176void CXFA_ScriptContext::GlobalPropertySetter(CFXJSE_Value* pObject, 177 const CFX_ByteStringC& szPropName, 178 CFXJSE_Value* pValue) { 179 CXFA_Object* lpOrginalNode = ToObject(pObject, nullptr); 180 CXFA_Document* pDoc = lpOrginalNode->GetDocument(); 181 CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); 182 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(lpOrginalNode); 183 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); 184 uint32_t dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings | 185 XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | 186 XFA_RESOLVENODE_Attributes; 187 CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); 188 if (lpOrginalNode->IsVariablesThis()) 189 pRefNode = ToNode(lpCurNode); 190 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, 191 dwFlag, true)) { 192 return; 193 } 194 if (lpOrginalNode->IsVariablesThis()) { 195 if (pValue && pValue->IsUndefined()) { 196 pObject->SetObjectOwnProperty(szPropName, pValue); 197 return; 198 } 199 } 200 CXFA_FFNotify* pNotify = pDoc->GetNotify(); 201 if (!pNotify) { 202 return; 203 } 204 pNotify->GetDocEnvironment()->SetGlobalProperty(pNotify->GetHDOC(), 205 szPropName, pValue); 206} 207bool CXFA_ScriptContext::QueryNodeByFlag(CXFA_Node* refNode, 208 const CFX_WideStringC& propname, 209 CFXJSE_Value* pValue, 210 uint32_t dwFlag, 211 bool bSetting) { 212 if (!refNode) 213 return false; 214 XFA_RESOLVENODE_RS resolveRs; 215 if (ResolveObjects(refNode, propname, resolveRs, dwFlag) <= 0) 216 return false; 217 if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) { 218 pValue->Assign(GetJSValueFromMap(resolveRs.nodes[0])); 219 return true; 220 } 221 if (resolveRs.dwFlags == XFA_RESOVENODE_RSTYPE_Attribute) { 222 const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = resolveRs.pScriptAttribute; 223 if (lpAttributeInfo) { 224 (resolveRs.nodes[0]->*(lpAttributeInfo->lpfnCallback))( 225 pValue, bSetting, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute); 226 } 227 } 228 return true; 229} 230void CXFA_ScriptContext::GlobalPropertyGetter(CFXJSE_Value* pObject, 231 const CFX_ByteStringC& szPropName, 232 CFXJSE_Value* pValue) { 233 CXFA_Object* pOriginalObject = ToObject(pObject, nullptr); 234 CXFA_Document* pDoc = pOriginalObject->GetDocument(); 235 CXFA_ScriptContext* lpScriptContext = pDoc->GetScriptContext(); 236 CXFA_Object* lpCurNode = lpScriptContext->GetVariablesThis(pOriginalObject); 237 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); 238 if (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Formcalc) { 239 if (szPropName == kFormCalcRuntime) { 240 lpScriptContext->m_FM2JSContext->GlobalPropertyGetter(pValue); 241 return; 242 } 243 XFA_HashCode uHashCode = static_cast<XFA_HashCode>( 244 FX_HashCode_GetW(wsPropName.AsStringC(), false)); 245 if (uHashCode != XFA_HASHCODE_Layout) { 246 CXFA_Object* pObj = 247 lpScriptContext->GetDocument()->GetXFAObject(uHashCode); 248 if (pObj) { 249 pValue->Assign(lpScriptContext->GetJSValueFromMap(pObj)); 250 return; 251 } 252 } 253 } 254 uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | 255 XFA_RESOLVENODE_Attributes; 256 CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); 257 if (pOriginalObject->IsVariablesThis()) { 258 pRefNode = ToNode(lpCurNode); 259 } 260 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, 261 dwFlag, false)) { 262 return; 263 } 264 dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings; 265 if (lpScriptContext->QueryNodeByFlag(pRefNode, wsPropName.AsStringC(), pValue, 266 dwFlag, false)) { 267 return; 268 } 269 CXFA_Object* pScriptObject = 270 lpScriptContext->GetVariablesThis(pOriginalObject, true); 271 if (pScriptObject && 272 lpScriptContext->QueryVariableValue(pScriptObject->AsNode(), szPropName, 273 pValue, true)) { 274 return; 275 } 276 CXFA_FFNotify* pNotify = pDoc->GetNotify(); 277 if (!pNotify) { 278 return; 279 } 280 pNotify->GetDocEnvironment()->GetGlobalProperty(pNotify->GetHDOC(), 281 szPropName, pValue); 282} 283void CXFA_ScriptContext::NormalPropertyGetter(CFXJSE_Value* pOriginalValue, 284 const CFX_ByteStringC& szPropName, 285 CFXJSE_Value* pReturnValue) { 286 CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); 287 if (!pOriginalObject) { 288 pReturnValue->SetUndefined(); 289 return; 290 } 291 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); 292 CXFA_ScriptContext* lpScriptContext = 293 pOriginalObject->GetDocument()->GetScriptContext(); 294 CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); 295 if (wsPropName == L"xfa") { 296 CFXJSE_Value* pValue = lpScriptContext->GetJSValueFromMap( 297 lpScriptContext->GetDocument()->GetRoot()); 298 pReturnValue->Assign(pValue); 299 return; 300 } 301 uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | 302 XFA_RESOLVENODE_Attributes; 303 bool bRet = lpScriptContext->QueryNodeByFlag( 304 ToNode(pObject), wsPropName.AsStringC(), pReturnValue, dwFlag, false); 305 if (bRet) { 306 return; 307 } 308 if (pObject == lpScriptContext->GetThisObject() || 309 (lpScriptContext->GetType() == XFA_SCRIPTLANGTYPE_Javascript && 310 !lpScriptContext->IsStrictScopeInJavaScript())) { 311 dwFlag = XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings; 312 bRet = lpScriptContext->QueryNodeByFlag( 313 ToNode(pObject), wsPropName.AsStringC(), pReturnValue, dwFlag, false); 314 } 315 if (bRet) { 316 return; 317 } 318 CXFA_Object* pScriptObject = 319 lpScriptContext->GetVariablesThis(pOriginalObject, true); 320 if (pScriptObject) { 321 bRet = lpScriptContext->QueryVariableValue(ToNode(pScriptObject), 322 szPropName, pReturnValue, true); 323 } 324 if (!bRet) { 325 pReturnValue->SetUndefined(); 326 } 327} 328void CXFA_ScriptContext::NormalPropertySetter(CFXJSE_Value* pOriginalValue, 329 const CFX_ByteStringC& szPropName, 330 CFXJSE_Value* pReturnValue) { 331 CXFA_Object* pOriginalObject = ToObject(pOriginalValue, nullptr); 332 if (!pOriginalObject) 333 return; 334 335 CXFA_ScriptContext* lpScriptContext = 336 pOriginalObject->GetDocument()->GetScriptContext(); 337 CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject); 338 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); 339 const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = XFA_GetScriptAttributeByName( 340 pObject->GetElementType(), wsPropName.AsStringC()); 341 if (lpAttributeInfo) { 342 (pObject->*(lpAttributeInfo->lpfnCallback))( 343 pReturnValue, true, (XFA_ATTRIBUTE)lpAttributeInfo->eAttribute); 344 } else { 345 if (pObject->IsNode()) { 346 if (wsPropName.GetAt(0) == '#') { 347 wsPropName = wsPropName.Right(wsPropName.GetLength() - 1); 348 } 349 CXFA_Node* pNode = ToNode(pObject); 350 CXFA_Node* pPropOrChild = nullptr; 351 XFA_Element eType = XFA_GetElementTypeForName(wsPropName.AsStringC()); 352 if (eType != XFA_Element::Unknown) 353 pPropOrChild = pNode->GetProperty(0, eType); 354 else 355 pPropOrChild = pNode->GetFirstChildByName(wsPropName.AsStringC()); 356 357 if (pPropOrChild) { 358 CFX_WideString wsDefaultName(L"{default}"); 359 const XFA_SCRIPTATTRIBUTEINFO* lpAttrInfo = 360 XFA_GetScriptAttributeByName(pPropOrChild->GetElementType(), 361 wsDefaultName.AsStringC()); 362 if (lpAttrInfo) { 363 (pPropOrChild->*(lpAttrInfo->lpfnCallback))( 364 pReturnValue, true, (XFA_ATTRIBUTE)lpAttrInfo->eAttribute); 365 return; 366 } 367 } 368 } 369 CXFA_Object* pScriptObject = 370 lpScriptContext->GetVariablesThis(pOriginalObject, true); 371 if (pScriptObject) { 372 lpScriptContext->QueryVariableValue(ToNode(pScriptObject), szPropName, 373 pReturnValue, false); 374 } 375 } 376} 377int32_t CXFA_ScriptContext::NormalPropTypeGetter( 378 CFXJSE_Value* pOriginalValue, 379 const CFX_ByteStringC& szPropName, 380 bool bQueryIn) { 381 CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); 382 if (!pObject) 383 return FXJSE_ClassPropType_None; 384 385 CXFA_ScriptContext* lpScriptContext = 386 pObject->GetDocument()->GetScriptContext(); 387 pObject = lpScriptContext->GetVariablesThis(pObject); 388 XFA_Element eType = pObject->GetElementType(); 389 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); 390 if (GetMethodByName(eType, wsPropName.AsStringC())) { 391 return FXJSE_ClassPropType_Method; 392 } 393 if (bQueryIn && 394 !XFA_GetScriptAttributeByName(eType, wsPropName.AsStringC())) { 395 return FXJSE_ClassPropType_None; 396 } 397 return FXJSE_ClassPropType_Property; 398} 399int32_t CXFA_ScriptContext::GlobalPropTypeGetter( 400 CFXJSE_Value* pOriginalValue, 401 const CFX_ByteStringC& szPropName, 402 bool bQueryIn) { 403 CXFA_Object* pObject = ToObject(pOriginalValue, nullptr); 404 if (!pObject) 405 return FXJSE_ClassPropType_None; 406 407 CXFA_ScriptContext* lpScriptContext = 408 pObject->GetDocument()->GetScriptContext(); 409 pObject = lpScriptContext->GetVariablesThis(pObject); 410 XFA_Element eType = pObject->GetElementType(); 411 CFX_WideString wsPropName = CFX_WideString::FromUTF8(szPropName); 412 if (GetMethodByName(eType, wsPropName.AsStringC())) { 413 return FXJSE_ClassPropType_Method; 414 } 415 return FXJSE_ClassPropType_Property; 416} 417void CXFA_ScriptContext::NormalMethodCall(CFXJSE_Value* pThis, 418 const CFX_ByteStringC& szFuncName, 419 CFXJSE_Arguments& args) { 420 CXFA_Object* pObject = ToObject(pThis, nullptr); 421 if (!pObject) 422 return; 423 424 CXFA_ScriptContext* lpScriptContext = 425 pObject->GetDocument()->GetScriptContext(); 426 pObject = lpScriptContext->GetVariablesThis(pObject); 427 CFX_WideString wsFunName = CFX_WideString::FromUTF8(szFuncName); 428 const XFA_METHODINFO* lpMethodInfo = 429 GetMethodByName(pObject->GetElementType(), wsFunName.AsStringC()); 430 if (!lpMethodInfo) 431 return; 432 433 (pObject->*(lpMethodInfo->lpfnCallback))(&args); 434} 435bool CXFA_ScriptContext::IsStrictScopeInJavaScript() { 436 return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping); 437} 438XFA_SCRIPTLANGTYPE CXFA_ScriptContext::GetType() { 439 return m_eScriptType; 440} 441void CXFA_ScriptContext::DefineJsContext() { 442 m_JsContext.reset(CFXJSE_Context::Create(m_pIsolate, &GlobalClassDescriptor, 443 m_pDocument->GetRoot())); 444 RemoveBuiltInObjs(m_JsContext.get()); 445 m_JsContext->EnableCompatibleMode(); 446} 447CFXJSE_Context* CXFA_ScriptContext::CreateVariablesContext( 448 CXFA_Node* pScriptNode, 449 CXFA_Node* pSubform) { 450 if (!pScriptNode || !pSubform) 451 return nullptr; 452 453 CFXJSE_Context* pVariablesContext = 454 CFXJSE_Context::Create(m_pIsolate, &VariablesClassDescriptor, 455 new CXFA_ThisProxy(pSubform, pScriptNode)); 456 RemoveBuiltInObjs(pVariablesContext); 457 pVariablesContext->EnableCompatibleMode(); 458 m_mapVariableToContext[pScriptNode] = pVariablesContext; 459 return pVariablesContext; 460} 461CXFA_Object* CXFA_ScriptContext::GetVariablesThis(CXFA_Object* pObject, 462 bool bScriptNode) { 463 if (!pObject->IsVariablesThis()) 464 return pObject; 465 466 CXFA_ThisProxy* pProxy = static_cast<CXFA_ThisProxy*>(pObject); 467 return bScriptNode ? pProxy->GetScriptNode() : pProxy->GetThisNode(); 468} 469 470bool CXFA_ScriptContext::RunVariablesScript(CXFA_Node* pScriptNode) { 471 if (!pScriptNode) 472 return false; 473 474 if (pScriptNode->GetElementType() != XFA_Element::Script) 475 return true; 476 477 CXFA_Node* pParent = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); 478 if (!pParent || pParent->GetElementType() != XFA_Element::Variables) 479 return false; 480 481 auto it = m_mapVariableToContext.find(pScriptNode); 482 if (it != m_mapVariableToContext.end() && it->second) 483 return true; 484 485 CXFA_Node* pTextNode = pScriptNode->GetNodeItem(XFA_NODEITEM_FirstChild); 486 if (!pTextNode) 487 return false; 488 489 CFX_WideStringC wsScript; 490 if (!pTextNode->TryCData(XFA_ATTRIBUTE_Value, wsScript)) 491 return false; 492 493 CFX_ByteString btScript = FX_UTF8Encode(wsScript); 494 std::unique_ptr<CFXJSE_Value> hRetValue(new CFXJSE_Value(m_pIsolate)); 495 CXFA_Node* pThisObject = pParent->GetNodeItem(XFA_NODEITEM_Parent); 496 CFXJSE_Context* pVariablesContext = 497 CreateVariablesContext(pScriptNode, pThisObject); 498 CXFA_Object* pOriginalObject = m_pThisObject; 499 m_pThisObject = pThisObject; 500 bool bRet = 501 pVariablesContext->ExecuteScript(btScript.c_str(), hRetValue.get()); 502 m_pThisObject = pOriginalObject; 503 return bRet; 504} 505 506bool CXFA_ScriptContext::QueryVariableValue(CXFA_Node* pScriptNode, 507 const CFX_ByteStringC& szPropName, 508 CFXJSE_Value* pValue, 509 bool bGetter) { 510 if (!pScriptNode || pScriptNode->GetElementType() != XFA_Element::Script) 511 return false; 512 513 CXFA_Node* variablesNode = pScriptNode->GetNodeItem(XFA_NODEITEM_Parent); 514 if (!variablesNode || 515 variablesNode->GetElementType() != XFA_Element::Variables) 516 return false; 517 518 auto it = m_mapVariableToContext.find(pScriptNode); 519 if (it == m_mapVariableToContext.end() || !it->second) 520 return false; 521 522 void* lpVariables = it->second; 523 bool bRes = false; 524 CFXJSE_Context* pVariableContext = static_cast<CFXJSE_Context*>(lpVariables); 525 std::unique_ptr<CFXJSE_Value> pObject = pVariableContext->GetGlobalObject(); 526 std::unique_ptr<CFXJSE_Value> hVariableValue(new CFXJSE_Value(m_pIsolate)); 527 if (!bGetter) { 528 pObject->SetObjectOwnProperty(szPropName, pValue); 529 bRes = true; 530 } else if (pObject->HasObjectOwnProperty(szPropName, false)) { 531 pObject->GetObjectProperty(szPropName, hVariableValue.get()); 532 if (hVariableValue->IsFunction()) 533 pValue->SetFunctionBind(hVariableValue.get(), pObject.get()); 534 else if (bGetter) 535 pValue->Assign(hVariableValue.get()); 536 else 537 hVariableValue.get()->Assign(pValue); 538 bRes = true; 539 } 540 return bRes; 541} 542 543void CXFA_ScriptContext::DefineJsClass() { 544 m_pJsClass = CFXJSE_Class::Create(m_JsContext.get(), &NormalClassDescriptor); 545} 546 547void CXFA_ScriptContext::RemoveBuiltInObjs(CFXJSE_Context* pContext) const { 548 static const CFX_ByteStringC OBJ_NAME[2] = {"Number", "Date"}; 549 std::unique_ptr<CFXJSE_Value> pObject = pContext->GetGlobalObject(); 550 std::unique_ptr<CFXJSE_Value> hProp(new CFXJSE_Value(m_pIsolate)); 551 for (int i = 0; i < 2; ++i) { 552 if (pObject->GetObjectProperty(OBJ_NAME[i], hProp.get())) 553 pObject->DeleteObjectProperty(OBJ_NAME[i]); 554 } 555} 556CFXJSE_Class* CXFA_ScriptContext::GetJseNormalClass() { 557 return m_pJsClass; 558} 559int32_t CXFA_ScriptContext::ResolveObjects(CXFA_Object* refNode, 560 const CFX_WideStringC& wsExpression, 561 XFA_RESOLVENODE_RS& resolveNodeRS, 562 uint32_t dwStyles, 563 CXFA_Node* bindNode) { 564 if (wsExpression.IsEmpty()) { 565 return 0; 566 } 567 if (m_eScriptType != XFA_SCRIPTLANGTYPE_Formcalc || 568 (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { 569 m_upObjectArray.RemoveAll(); 570 } 571 if (refNode && refNode->IsNode() && 572 (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { 573 m_upObjectArray.Add(refNode->AsNode()); 574 } 575 bool bNextCreate = false; 576 if (dwStyles & XFA_RESOLVENODE_CreateNode) { 577 m_ResolveProcessor->GetNodeHelper()->SetCreateNodeType(bindNode); 578 } 579 m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = nullptr; 580 m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart = -1; 581 CXFA_ResolveNodesData rndFind; 582 int32_t nStart = 0; 583 int32_t nLevel = 0; 584 int32_t nRet = -1; 585 rndFind.m_pSC = this; 586 CXFA_ObjArray findNodes; 587 findNodes.Add(refNode ? refNode : m_pDocument->GetRoot()); 588 int32_t nNodes = 0; 589 while (true) { 590 nNodes = findNodes.GetSize(); 591 int32_t i = 0; 592 rndFind.m_dwStyles = dwStyles; 593 m_ResolveProcessor->SetCurStart(nStart); 594 nStart = m_ResolveProcessor->GetFilter(wsExpression, nStart, rndFind); 595 if (nStart < 1) { 596 if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) { 597 CXFA_Node* pDataNode = nullptr; 598 nStart = m_ResolveProcessor->GetNodeHelper()->m_iCurAllStart; 599 if (nStart != -1) { 600 pDataNode = m_pDocument->GetNotBindNode(findNodes); 601 if (pDataNode) { 602 findNodes.RemoveAll(); 603 findNodes.Add(pDataNode); 604 break; 605 } 606 } else { 607 pDataNode = findNodes[0]->AsNode(); 608 findNodes.RemoveAll(); 609 findNodes.Add(pDataNode); 610 break; 611 } 612 dwStyles |= XFA_RESOLVENODE_Bind; 613 findNodes.RemoveAll(); 614 findNodes.Add(m_ResolveProcessor->GetNodeHelper()->m_pAllStartParent); 615 continue; 616 } else { 617 break; 618 } 619 } 620 if (bNextCreate) { 621 bool bCreate = 622 m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( 623 rndFind.m_wsName, rndFind.m_wsCondition, 624 nStart == wsExpression.GetLength(), this); 625 if (bCreate) { 626 continue; 627 } else { 628 break; 629 } 630 } 631 CXFA_ObjArray retNodes; 632 while (i < nNodes) { 633 bool bDataBind = false; 634 if (((dwStyles & XFA_RESOLVENODE_Bind) || 635 (dwStyles & XFA_RESOLVENODE_CreateNode)) && 636 nNodes > 1) { 637 CXFA_ResolveNodesData rndBind; 638 m_ResolveProcessor->GetFilter(wsExpression, nStart, rndBind); 639 m_ResolveProcessor->SetIndexDataBind(rndBind.m_wsCondition, i, nNodes); 640 bDataBind = true; 641 } 642 rndFind.m_CurNode = findNodes[i++]; 643 rndFind.m_nLevel = nLevel; 644 rndFind.m_dwFlag = XFA_RESOVENODE_RSTYPE_Nodes; 645 nRet = m_ResolveProcessor->Resolve(rndFind); 646 if (nRet < 1) { 647 continue; 648 } 649 if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute && 650 rndFind.m_pScriptAttribute && nStart < wsExpression.GetLength()) { 651 std::unique_ptr<CFXJSE_Value> pValue(new CFXJSE_Value(m_pIsolate)); 652 (rndFind.m_Nodes[0]->*(rndFind.m_pScriptAttribute->lpfnCallback))( 653 pValue.get(), false, 654 (XFA_ATTRIBUTE)rndFind.m_pScriptAttribute->eAttribute); 655 rndFind.m_Nodes.SetAt(0, ToObject(pValue.get(), nullptr)); 656 } 657 int32_t iSize = m_upObjectArray.GetSize(); 658 if (iSize) { 659 m_upObjectArray.RemoveAt(iSize - 1); 660 } 661 retNodes.Append(rndFind.m_Nodes); 662 rndFind.m_Nodes.RemoveAll(); 663 if (bDataBind) { 664 break; 665 } 666 } 667 findNodes.RemoveAll(); 668 nNodes = retNodes.GetSize(); 669 if (nNodes < 1) { 670 if (dwStyles & XFA_RESOLVENODE_CreateNode) { 671 bNextCreate = true; 672 if (!m_ResolveProcessor->GetNodeHelper()->m_pCreateParent) { 673 m_ResolveProcessor->GetNodeHelper()->m_pCreateParent = 674 ToNode(rndFind.m_CurNode); 675 m_ResolveProcessor->GetNodeHelper()->m_iCreateCount = 1; 676 } 677 bool bCreate = 678 m_ResolveProcessor->GetNodeHelper()->ResolveNodes_CreateNode( 679 rndFind.m_wsName, rndFind.m_wsCondition, 680 nStart == wsExpression.GetLength(), this); 681 if (bCreate) { 682 continue; 683 } else { 684 break; 685 } 686 } else { 687 break; 688 } 689 } 690 findNodes.Copy(retNodes); 691 rndFind.m_Nodes.RemoveAll(); 692 if (nLevel == 0) { 693 dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings); 694 } 695 nLevel++; 696 } 697 if (!bNextCreate) { 698 resolveNodeRS.dwFlags = rndFind.m_dwFlag; 699 if (nNodes > 0) { 700 resolveNodeRS.nodes.Append(findNodes); 701 } 702 if (rndFind.m_dwFlag == XFA_RESOVENODE_RSTYPE_Attribute) { 703 resolveNodeRS.pScriptAttribute = rndFind.m_pScriptAttribute; 704 return 1; 705 } 706 } 707 if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind | 708 XFA_RESOLVENODE_BindNew)) { 709 m_ResolveProcessor->SetResultCreateNode(resolveNodeRS, 710 rndFind.m_wsCondition); 711 if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) { 712 resolveNodeRS.dwFlags = XFA_RESOVENODE_RSTYPE_ExistNodes; 713 } 714 return resolveNodeRS.nodes.GetSize(); 715 } 716 return nNodes; 717} 718 719void CXFA_ScriptContext::AddToCacheList(std::unique_ptr<CXFA_NodeList> pList) { 720 m_CacheList.push_back(std::move(pList)); 721} 722 723CFXJSE_Value* CXFA_ScriptContext::GetJSValueFromMap(CXFA_Object* pObject) { 724 if (!pObject) 725 return nullptr; 726 if (pObject->IsNode()) 727 RunVariablesScript(pObject->AsNode()); 728 729 auto iter = m_mapObjectToValue.find(pObject); 730 if (iter != m_mapObjectToValue.end()) 731 return iter->second.get(); 732 733 std::unique_ptr<CFXJSE_Value> jsValue(new CFXJSE_Value(m_pIsolate)); 734 jsValue->SetObject(pObject, m_pJsClass); 735 CFXJSE_Value* pValue = jsValue.get(); 736 m_mapObjectToValue.insert(std::make_pair(pObject, std::move(jsValue))); 737 return pValue; 738} 739int32_t CXFA_ScriptContext::GetIndexByName(CXFA_Node* refNode) { 740 CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); 741 return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, 742 lpNodeHelper->NodeIsProperty(refNode), false); 743} 744int32_t CXFA_ScriptContext::GetIndexByClassName(CXFA_Node* refNode) { 745 CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); 746 return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, 747 lpNodeHelper->NodeIsProperty(refNode), true); 748} 749void CXFA_ScriptContext::GetSomExpression(CXFA_Node* refNode, 750 CFX_WideString& wsExpression) { 751 CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); 752 lpNodeHelper->GetNameExpression(refNode, wsExpression, true, 753 XFA_LOGIC_Transparent); 754} 755void CXFA_ScriptContext::SetNodesOfRunScript(CXFA_NodeArray* pArray) { 756 m_pScriptNodeArray = pArray; 757} 758void CXFA_ScriptContext::AddNodesOfRunScript(const CXFA_NodeArray& nodes) { 759 if (!m_pScriptNodeArray) 760 return; 761 if (nodes.GetSize() > 0) 762 m_pScriptNodeArray->Copy(nodes); 763} 764void CXFA_ScriptContext::AddNodesOfRunScript(CXFA_Node* pNode) { 765 if (!m_pScriptNodeArray) 766 return; 767 if (m_pScriptNodeArray->Find(pNode) == -1) 768 m_pScriptNodeArray->Add(pNode); 769} 770