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