// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "fxjs/cfxjse_engine.h" #include #include "core/fxcrt/autorestorer.h" #include "core/fxcrt/cfx_widetextbuf.h" #include "core/fxcrt/fx_extension.h" #include "fxjs/cfxjse_class.h" #include "fxjs/cfxjse_context.h" #include "fxjs/cfxjse_formcalc_context.h" #include "fxjs/cfxjse_resolveprocessor.h" #include "fxjs/cfxjse_value.h" #include "fxjs/cjs_runtime.h" #include "fxjs/xfa/cjx_object.h" #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/cxfa_ffdoc.h" #include "xfa/fxfa/cxfa_ffnotify.h" #include "xfa/fxfa/parser/cxfa_document.h" #include "xfa/fxfa/parser/cxfa_localemgr.h" #include "xfa/fxfa/parser/cxfa_node.h" #include "xfa/fxfa/parser/cxfa_nodehelper.h" #include "xfa/fxfa/parser/cxfa_object.h" #include "xfa/fxfa/parser/cxfa_thisproxy.h" #include "xfa/fxfa/parser/cxfa_treelist.h" #include "xfa/fxfa/parser/xfa_basic_data.h" #include "xfa/fxfa/parser/xfa_resolvenode_rs.h" #include "xfa/fxfa/parser/xfa_utils.h" using pdfium::fxjse::kClassTag; const FXJSE_CLASS_DESCRIPTOR GlobalClassDescriptor = { kClassTag, // tag "Root", // name nullptr, // methods 0, // method count CFXJSE_Engine::GlobalPropTypeGetter, CFXJSE_Engine::GlobalPropertyGetter, CFXJSE_Engine::GlobalPropertySetter, CFXJSE_Engine::NormalMethodCall, }; const FXJSE_CLASS_DESCRIPTOR NormalClassDescriptor = { kClassTag, // tag "XFAObject", // name nullptr, // methods 0, // method count CFXJSE_Engine::NormalPropTypeGetter, CFXJSE_Engine::NormalPropertyGetter, CFXJSE_Engine::NormalPropertySetter, CFXJSE_Engine::NormalMethodCall, }; const FXJSE_CLASS_DESCRIPTOR VariablesClassDescriptor = { kClassTag, // tag "XFAScriptObject", // name nullptr, // methods 0, // method count CFXJSE_Engine::NormalPropTypeGetter, CFXJSE_Engine::GlobalPropertyGetter, CFXJSE_Engine::GlobalPropertySetter, CFXJSE_Engine::NormalMethodCall, }; namespace { const char kFormCalcRuntime[] = "pfm_rt"; CXFA_ThisProxy* ToThisProxy(CFXJSE_Value* pValue) { CFXJSE_HostObject* pHostObject = pValue->ToHostObject(); return pHostObject ? ToThisProxy(pHostObject->AsCXFAObject()) : nullptr; } } // namespace // static CXFA_Object* CFXJSE_Engine::ToObject( const v8::FunctionCallbackInfo& info) { if (!info.Holder()->IsObject()) return nullptr; CFXJSE_HostObject* pHostObj = FXJSE_RetrieveObjectBinding(info.Holder().As()); return pHostObj ? pHostObj->AsCXFAObject() : nullptr; } // static. CXFA_Object* CFXJSE_Engine::ToObject(CFXJSE_Value* pValue) { CFXJSE_HostObject* pHostObj = pValue->ToHostObject(); return pHostObj ? pHostObj->AsCXFAObject() : nullptr; } CFXJSE_Engine::CFXJSE_Engine(CXFA_Document* pDocument, CJS_Runtime* fxjs_runtime) : CFX_V8(fxjs_runtime->GetIsolate()), m_pSubordinateRuntime(fxjs_runtime), m_pDocument(pDocument), m_JsContext(CFXJSE_Context::Create(fxjs_runtime->GetIsolate(), &GlobalClassDescriptor, pDocument->GetRoot())), m_ResolveProcessor(pdfium::MakeUnique()) { RemoveBuiltInObjs(m_JsContext.get()); m_JsContext->EnableCompatibleMode(); // Don't know if this can happen before we remove the builtin objs and set // compatibility mode. m_pJsClass = CFXJSE_Class::Create(m_JsContext.get(), &NormalClassDescriptor, false); } CFXJSE_Engine::~CFXJSE_Engine() { for (const auto& pair : m_mapVariableToContext) delete ToThisProxy(pair.second->GetGlobalObject().get()); } bool CFXJSE_Engine::RunScript(CXFA_Script::Type eScriptType, const WideStringView& wsScript, CFXJSE_Value* hRetValue, CXFA_Object* pThisObject) { ByteString btScript; AutoRestorer typeRestorer(&m_eScriptType); m_eScriptType = eScriptType; if (eScriptType == CXFA_Script::Type::Formcalc) { if (!m_FM2JSContext) { m_FM2JSContext = pdfium::MakeUnique( GetIsolate(), m_JsContext.get(), m_pDocument.Get()); } CFX_WideTextBuf wsJavaScript; if (!CFXJSE_FormCalcContext::Translate(wsScript, &wsJavaScript)) { hRetValue->SetUndefined(); return false; } btScript = FX_UTF8Encode(wsJavaScript.AsStringView()); } else { btScript = FX_UTF8Encode(wsScript); } AutoRestorer> nodeRestorer(&m_pThisObject); m_pThisObject = pThisObject; CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : nullptr; IJS_Runtime::ScopedEventContext ctx(m_pSubordinateRuntime.Get()); return m_JsContext->ExecuteScript(btScript.c_str(), hRetValue, pValue); } bool CFXJSE_Engine::QueryNodeByFlag(CXFA_Node* refNode, const WideStringView& propname, CFXJSE_Value* pValue, uint32_t dwFlag, bool bSetting) { if (!refNode) return false; XFA_RESOLVENODE_RS resolveRs; if (!ResolveObjects(refNode, propname, &resolveRs, dwFlag, nullptr)) return false; if (resolveRs.dwFlags == XFA_ResolveNode_RSType_Nodes) { pValue->Assign(GetJSValueFromMap(resolveRs.objects.front().Get())); return true; } if (resolveRs.dwFlags == XFA_ResolveNode_RSType_Attribute) { const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = resolveRs.pScriptAttribute.Get(); if (lpAttributeInfo) { CJX_Object* jsObject = resolveRs.objects.front()->JSObject(); (jsObject->*(lpAttributeInfo->callback))(pValue, bSetting, lpAttributeInfo->attribute); } } return true; } void CFXJSE_Engine::GlobalPropertySetter(CFXJSE_Value* pObject, const ByteStringView& szPropName, CFXJSE_Value* pValue) { CXFA_Object* lpOrginalNode = ToObject(pObject); CXFA_Document* pDoc = lpOrginalNode->GetDocument(); CFXJSE_Engine* lpScriptContext = pDoc->GetScriptContext(); CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); if (lpOrginalNode->IsThisProxy()) pRefNode = ToNode(lpScriptContext->GetVariablesThis(lpOrginalNode, false)); WideString wsPropName = WideString::FromUTF8(szPropName); if (lpScriptContext->QueryNodeByFlag( pRefNode, wsPropName.AsStringView(), pValue, XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Attributes, true)) { return; } if (lpOrginalNode->IsThisProxy()) { if (pValue && pValue->IsUndefined()) { pObject->SetObjectOwnProperty(szPropName, pValue); return; } } CXFA_FFNotify* pNotify = pDoc->GetNotify(); if (!pNotify) return; CXFA_FFDoc* hDoc = pNotify->GetHDOC(); hDoc->GetDocEnvironment()->SetPropertyInNonXFAGlobalObject(hDoc, szPropName, pValue); } void CFXJSE_Engine::GlobalPropertyGetter(CFXJSE_Value* pObject, const ByteStringView& szPropName, CFXJSE_Value* pValue) { CXFA_Object* pOriginalObject = ToObject(pObject); CXFA_Document* pDoc = pOriginalObject->GetDocument(); CFXJSE_Engine* lpScriptContext = pDoc->GetScriptContext(); WideString wsPropName = WideString::FromUTF8(szPropName); if (lpScriptContext->GetType() == CXFA_Script::Type::Formcalc) { if (szPropName == kFormCalcRuntime) { lpScriptContext->m_FM2JSContext->GlobalPropertyGetter(pValue); return; } XFA_HashCode uHashCode = static_cast( FX_HashCode_GetW(wsPropName.AsStringView(), false)); if (uHashCode != XFA_HASHCODE_Layout) { CXFA_Object* pObj = lpScriptContext->GetDocument()->GetXFAObject(uHashCode); if (pObj) { pValue->Assign(lpScriptContext->GetJSValueFromMap(pObj)); return; } } } CXFA_Node* pRefNode = ToNode(lpScriptContext->GetThisObject()); if (pOriginalObject->IsThisProxy()) pRefNode = ToNode(lpScriptContext->GetVariablesThis(pOriginalObject, false)); if (lpScriptContext->QueryNodeByFlag( pRefNode, wsPropName.AsStringView(), pValue, XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Attributes, false)) { return; } if (lpScriptContext->QueryNodeByFlag( pRefNode, wsPropName.AsStringView(), pValue, XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings, false)) { return; } CXFA_Object* pScriptObject = lpScriptContext->GetVariablesThis(pOriginalObject, true); if (pScriptObject && lpScriptContext->QueryVariableValue( pScriptObject->AsNode(), szPropName, pValue, true)) { return; } CXFA_FFNotify* pNotify = pDoc->GetNotify(); if (!pNotify) return; CXFA_FFDoc* hDoc = pNotify->GetHDOC(); hDoc->GetDocEnvironment()->GetPropertyFromNonXFAGlobalObject(hDoc, szPropName, pValue); } int32_t CFXJSE_Engine::GlobalPropTypeGetter(CFXJSE_Value* pOriginalValue, const ByteStringView& szPropName, bool bQueryIn) { CXFA_Object* pObject = ToObject(pOriginalValue); if (!pObject) return FXJSE_ClassPropType_None; CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext(); pObject = lpScriptContext->GetVariablesThis(pObject, false); WideString wsPropName = WideString::FromUTF8(szPropName); if (pObject->JSObject()->HasMethod(wsPropName)) return FXJSE_ClassPropType_Method; return FXJSE_ClassPropType_Property; } void CFXJSE_Engine::NormalPropertyGetter(CFXJSE_Value* pOriginalValue, const ByteStringView& szPropName, CFXJSE_Value* pReturnValue) { CXFA_Object* pOriginalObject = ToObject(pOriginalValue); if (!pOriginalObject) { pReturnValue->SetUndefined(); return; } WideString wsPropName = WideString::FromUTF8(szPropName); CFXJSE_Engine* lpScriptContext = pOriginalObject->GetDocument()->GetScriptContext(); CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject, false); if (wsPropName == L"xfa") { CFXJSE_Value* pValue = lpScriptContext->GetJSValueFromMap( lpScriptContext->GetDocument()->GetRoot()); pReturnValue->Assign(pValue); return; } bool bRet = lpScriptContext->QueryNodeByFlag( ToNode(pObject), wsPropName.AsStringView(), pReturnValue, XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Attributes, false); if (bRet) return; if (pObject == lpScriptContext->GetThisObject() || (lpScriptContext->GetType() == CXFA_Script::Type::Javascript && !lpScriptContext->IsStrictScopeInJavaScript())) { bRet = lpScriptContext->QueryNodeByFlag( ToNode(pObject), wsPropName.AsStringView(), pReturnValue, XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings, false); } if (bRet) return; CXFA_Object* pScriptObject = lpScriptContext->GetVariablesThis(pOriginalObject, true); if (pScriptObject) { bRet = lpScriptContext->QueryVariableValue(ToNode(pScriptObject), szPropName, pReturnValue, true); if (!bRet) { const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = XFA_GetScriptAttributeByName(pObject->GetElementType(), wsPropName.AsStringView()); if (lpAttributeInfo) { CJX_Object* jsObject = pObject->JSObject(); (jsObject->*(lpAttributeInfo->callback))(pReturnValue, false, lpAttributeInfo->attribute); return; } } CXFA_FFNotify* pNotify = pObject->GetDocument()->GetNotify(); if (!pNotify) { pReturnValue->SetUndefined(); return; } CXFA_FFDoc* hDoc = pNotify->GetHDOC(); if (hDoc->GetDocEnvironment()->GetPropertyFromNonXFAGlobalObject( hDoc, szPropName, pReturnValue)) { return; } } if (!bRet) pReturnValue->SetUndefined(); } void CFXJSE_Engine::NormalPropertySetter(CFXJSE_Value* pOriginalValue, const ByteStringView& szPropName, CFXJSE_Value* pReturnValue) { CXFA_Object* pOriginalObject = ToObject(pOriginalValue); if (!pOriginalObject) return; CFXJSE_Engine* lpScriptContext = pOriginalObject->GetDocument()->GetScriptContext(); CXFA_Object* pObject = lpScriptContext->GetVariablesThis(pOriginalObject, false); WideString wsPropName = WideString::FromUTF8(szPropName); const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = XFA_GetScriptAttributeByName( pObject->GetElementType(), wsPropName.AsStringView()); if (lpAttributeInfo) { CJX_Object* jsObject = pObject->JSObject(); (jsObject->*(lpAttributeInfo->callback))(pReturnValue, true, lpAttributeInfo->attribute); return; } if (pObject->IsNode()) { if (wsPropName[0] == '#') wsPropName = wsPropName.Right(wsPropName.GetLength() - 1); CXFA_Node* pNode = ToNode(pObject); CXFA_Node* pPropOrChild = nullptr; XFA_Element eType = CXFA_Node::NameToElement(wsPropName); if (eType != XFA_Element::Unknown) { pPropOrChild = pNode->JSObject()->GetOrCreateProperty(0, eType); } else { pPropOrChild = pNode->GetFirstChildByName(wsPropName.AsStringView()); } if (pPropOrChild) { const XFA_SCRIPTATTRIBUTEINFO* lpAttrInfo = XFA_GetScriptAttributeByName( pPropOrChild->GetElementType(), L"{default}"); if (lpAttrInfo) { pPropOrChild->JSObject()->Script_Som_DefaultValue( pReturnValue, true, XFA_Attribute::Unknown); return; } } } CXFA_Object* pScriptObject = lpScriptContext->GetVariablesThis(pOriginalObject, true); if (pScriptObject) { lpScriptContext->QueryVariableValue(ToNode(pScriptObject), szPropName, pReturnValue, false); } } int32_t CFXJSE_Engine::NormalPropTypeGetter(CFXJSE_Value* pOriginalValue, const ByteStringView& szPropName, bool bQueryIn) { CXFA_Object* pObject = ToObject(pOriginalValue); if (!pObject) return FXJSE_ClassPropType_None; CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext(); pObject = lpScriptContext->GetVariablesThis(pObject, false); XFA_Element eType = pObject->GetElementType(); WideString wsPropName = WideString::FromUTF8(szPropName); if (pObject->JSObject()->HasMethod(wsPropName)) return FXJSE_ClassPropType_Method; if (bQueryIn && !XFA_GetScriptAttributeByName(eType, wsPropName.AsStringView())) { return FXJSE_ClassPropType_None; } return FXJSE_ClassPropType_Property; } CJS_Result CFXJSE_Engine::NormalMethodCall( const v8::FunctionCallbackInfo& info, const WideString& functionName) { CXFA_Object* pObject = ToObject(info); if (!pObject) return CJS_Result::Failure(L"no Holder() present."); CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext(); pObject = lpScriptContext->GetVariablesThis(pObject, false); std::vector> parameters; for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) parameters.push_back(info[i]); return pObject->JSObject()->RunMethod(functionName, parameters); } bool CFXJSE_Engine::IsStrictScopeInJavaScript() { return m_pDocument->HasFlag(XFA_DOCFLAG_StrictScoping); } CXFA_Script::Type CFXJSE_Engine::GetType() { return m_eScriptType; } CFXJSE_Context* CFXJSE_Engine::CreateVariablesContext(CXFA_Node* pScriptNode, CXFA_Node* pSubform) { if (!pScriptNode || !pSubform) return nullptr; auto pNewContext = CFXJSE_Context::Create(GetIsolate(), &VariablesClassDescriptor, new CXFA_ThisProxy(pSubform, pScriptNode)); RemoveBuiltInObjs(pNewContext.get()); pNewContext->EnableCompatibleMode(); CFXJSE_Context* pResult = pNewContext.get(); m_mapVariableToContext[pScriptNode] = std::move(pNewContext); return pResult; } CXFA_Object* CFXJSE_Engine::GetVariablesThis(CXFA_Object* pObject, bool bScriptNode) { CXFA_ThisProxy* pProxy = ToThisProxy(pObject); if (!pProxy) return pObject; return bScriptNode ? pProxy->GetScriptNode() : pProxy->GetThisNode(); } bool CFXJSE_Engine::RunVariablesScript(CXFA_Node* pScriptNode) { if (!pScriptNode) return false; if (pScriptNode->GetElementType() != XFA_Element::Script) return true; CXFA_Node* pParent = pScriptNode->GetParent(); if (!pParent || pParent->GetElementType() != XFA_Element::Variables) return false; auto it = m_mapVariableToContext.find(pScriptNode); if (it != m_mapVariableToContext.end() && it->second) return true; CXFA_Node* pTextNode = pScriptNode->GetFirstChild(); if (!pTextNode) return false; Optional wsScript = pTextNode->JSObject()->TryCData(XFA_Attribute::Value, true); if (!wsScript) return false; ByteString btScript = wsScript->UTF8Encode(); auto hRetValue = pdfium::MakeUnique(GetIsolate()); CXFA_Node* pThisObject = pParent->GetParent(); CFXJSE_Context* pVariablesContext = CreateVariablesContext(pScriptNode, pThisObject); AutoRestorer> nodeRestorer(&m_pThisObject); m_pThisObject = pThisObject; return pVariablesContext->ExecuteScript(btScript.c_str(), hRetValue.get(), nullptr); } bool CFXJSE_Engine::QueryVariableValue(CXFA_Node* pScriptNode, const ByteStringView& szPropName, CFXJSE_Value* pValue, bool bGetter) { if (!pScriptNode || pScriptNode->GetElementType() != XFA_Element::Script) return false; CXFA_Node* variablesNode = pScriptNode->GetParent(); if (!variablesNode || variablesNode->GetElementType() != XFA_Element::Variables) return false; auto it = m_mapVariableToContext.find(pScriptNode); if (it == m_mapVariableToContext.end() || !it->second) return false; CFXJSE_Context* pVariableContext = it->second.get(); std::unique_ptr pObject = pVariableContext->GetGlobalObject(); auto hVariableValue = pdfium::MakeUnique(GetIsolate()); if (!bGetter) { pObject->SetObjectOwnProperty(szPropName, pValue); return true; } if (pObject->HasObjectOwnProperty(szPropName, false)) { pObject->GetObjectProperty(szPropName, hVariableValue.get()); if (hVariableValue->IsFunction()) pValue->SetFunctionBind(hVariableValue.get(), pObject.get()); else if (bGetter) pValue->Assign(hVariableValue.get()); else hVariableValue.get()->Assign(pValue); return true; } return false; } void CFXJSE_Engine::RemoveBuiltInObjs(CFXJSE_Context* pContext) const { const ByteStringView OBJ_NAME[2] = {"Number", "Date"}; std::unique_ptr pObject = pContext->GetGlobalObject(); auto hProp = pdfium::MakeUnique(GetIsolate()); for (int i = 0; i < 2; ++i) { if (pObject->GetObjectProperty(OBJ_NAME[i], hProp.get())) pObject->DeleteObjectProperty(OBJ_NAME[i]); } } bool CFXJSE_Engine::ResolveObjects(CXFA_Object* refObject, const WideStringView& wsExpression, XFA_RESOLVENODE_RS* resolveNodeRS, uint32_t dwStyles, CXFA_Node* bindNode) { if (wsExpression.IsEmpty()) return false; if (m_eScriptType != CXFA_Script::Type::Formcalc || (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { m_upObjectArray.clear(); } if (refObject && refObject->IsNode() && (dwStyles & (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings))) { m_upObjectArray.push_back(refObject->AsNode()); } bool bNextCreate = false; CXFA_NodeHelper* pNodeHelper = m_ResolveProcessor->GetNodeHelper(); if (dwStyles & XFA_RESOLVENODE_CreateNode) pNodeHelper->SetCreateNodeType(bindNode); pNodeHelper->m_pCreateParent = nullptr; pNodeHelper->m_iCurAllStart = -1; CFXJSE_ResolveNodeData rndFind(this); int32_t nStart = 0; int32_t nLevel = 0; std::vector> findObjects; findObjects.emplace_back(refObject ? refObject : m_pDocument->GetRoot()); int32_t nNodes = 0; while (true) { nNodes = pdfium::CollectionSize(findObjects); int32_t i = 0; rndFind.m_dwStyles = dwStyles; m_ResolveProcessor->SetCurStart(nStart); nStart = m_ResolveProcessor->GetFilter(wsExpression, nStart, rndFind); if (nStart < 1) { if ((dwStyles & XFA_RESOLVENODE_CreateNode) && !bNextCreate) { CXFA_Node* pDataNode = nullptr; nStart = pNodeHelper->m_iCurAllStart; if (nStart != -1) { pDataNode = m_pDocument->GetNotBindNode(findObjects); if (pDataNode) { findObjects.clear(); findObjects.emplace_back(pDataNode); break; } } else { pDataNode = findObjects.front()->AsNode(); findObjects.clear(); findObjects.emplace_back(pDataNode); break; } dwStyles |= XFA_RESOLVENODE_Bind; findObjects.clear(); findObjects.emplace_back(pNodeHelper->m_pAllStartParent.Get()); continue; } break; } if (bNextCreate) { bool bCreate = pNodeHelper->ResolveNodes_CreateNode( rndFind.m_wsName, rndFind.m_wsCondition, nStart == pdfium::base::checked_cast(wsExpression.GetLength()), this); if (bCreate) continue; break; } std::vector retObjects; while (i < nNodes) { bool bDataBind = false; if (((dwStyles & XFA_RESOLVENODE_Bind) || (dwStyles & XFA_RESOLVENODE_CreateNode)) && nNodes > 1) { CFXJSE_ResolveNodeData rndBind(nullptr); m_ResolveProcessor->GetFilter(wsExpression, nStart, rndBind); m_ResolveProcessor->SetIndexDataBind(rndBind.m_wsCondition, i, nNodes); bDataBind = true; } rndFind.m_CurObject = findObjects[i++].Get(); rndFind.m_nLevel = nLevel; rndFind.m_dwFlag = XFA_ResolveNode_RSType_Nodes; if (!m_ResolveProcessor->Resolve(rndFind)) continue; if (rndFind.m_dwFlag == XFA_ResolveNode_RSType_Attribute && rndFind.m_pScriptAttribute && nStart < pdfium::base::checked_cast(wsExpression.GetLength())) { auto pValue = pdfium::MakeUnique(GetIsolate()); CJX_Object* jsObject = rndFind.m_Objects.front()->JSObject(); (jsObject->*(rndFind.m_pScriptAttribute->callback))( pValue.get(), false, rndFind.m_pScriptAttribute->attribute); rndFind.m_Objects.front() = ToObject(pValue.get()); } if (!m_upObjectArray.empty()) m_upObjectArray.pop_back(); retObjects.insert(retObjects.end(), rndFind.m_Objects.begin(), rndFind.m_Objects.end()); rndFind.m_Objects.clear(); if (bDataBind) break; } findObjects.clear(); nNodes = pdfium::CollectionSize(retObjects); if (nNodes < 1) { if (dwStyles & XFA_RESOLVENODE_CreateNode) { bNextCreate = true; if (!pNodeHelper->m_pCreateParent) { pNodeHelper->m_pCreateParent = ToNode(rndFind.m_CurObject); pNodeHelper->m_iCreateCount = 1; } bool bCreate = pNodeHelper->ResolveNodes_CreateNode( rndFind.m_wsName, rndFind.m_wsCondition, nStart == pdfium::base::checked_cast(wsExpression.GetLength()), this); if (bCreate) continue; } break; } findObjects = std::vector>(retObjects.begin(), retObjects.end()); rndFind.m_Objects.clear(); if (nLevel == 0) dwStyles &= ~(XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings); nLevel++; } if (!bNextCreate) { resolveNodeRS->dwFlags = rndFind.m_dwFlag; if (nNodes > 0) { resolveNodeRS->objects.insert(resolveNodeRS->objects.end(), findObjects.begin(), findObjects.end()); } if (rndFind.m_dwFlag == XFA_ResolveNode_RSType_Attribute) { resolveNodeRS->pScriptAttribute = rndFind.m_pScriptAttribute; return 1; } } if (dwStyles & (XFA_RESOLVENODE_CreateNode | XFA_RESOLVENODE_Bind | XFA_RESOLVENODE_BindNew)) { if (pNodeHelper->m_pCreateParent) resolveNodeRS->objects.emplace_back(pNodeHelper->m_pCreateParent.Get()); else pNodeHelper->CreateNode_ForCondition(rndFind.m_wsCondition); resolveNodeRS->dwFlags = pNodeHelper->m_iCreateFlag; if (resolveNodeRS->dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) { if (pNodeHelper->m_iCurAllStart != -1) resolveNodeRS->dwFlags = XFA_ResolveNode_RSType_CreateNodeMidAll; } if (!bNextCreate && (dwStyles & XFA_RESOLVENODE_CreateNode)) resolveNodeRS->dwFlags = XFA_ResolveNode_RSType_ExistNodes; return !resolveNodeRS->objects.empty(); } return nNodes > 0; } void CFXJSE_Engine::AddToCacheList(std::unique_ptr pList) { m_CacheList.push_back(std::move(pList)); } CFXJSE_Value* CFXJSE_Engine::GetJSValueFromMap(CXFA_Object* pObject) { if (!pObject) return nullptr; if (pObject->IsNode()) RunVariablesScript(pObject->AsNode()); auto iter = m_mapObjectToValue.find(pObject); if (iter != m_mapObjectToValue.end()) return iter->second.get(); auto jsValue = pdfium::MakeUnique(GetIsolate()); jsValue->SetObject(pObject, m_pJsClass.Get()); CFXJSE_Value* pValue = jsValue.get(); m_mapObjectToValue.insert(std::make_pair(pObject, std::move(jsValue))); return pValue; } int32_t CFXJSE_Engine::GetIndexByName(CXFA_Node* refNode) { CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, lpNodeHelper->NodeIsProperty(refNode), false); } int32_t CFXJSE_Engine::GetIndexByClassName(CXFA_Node* refNode) { CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); return lpNodeHelper->GetIndex(refNode, XFA_LOGIC_Transparent, lpNodeHelper->NodeIsProperty(refNode), true); } WideString CFXJSE_Engine::GetSomExpression(CXFA_Node* refNode) { CXFA_NodeHelper* lpNodeHelper = m_ResolveProcessor->GetNodeHelper(); return lpNodeHelper->GetNameExpression(refNode, true); } void CFXJSE_Engine::SetNodesOfRunScript(std::vector* pArray) { m_pScriptNodeArray = pArray; } void CFXJSE_Engine::AddNodesOfRunScript(CXFA_Node* pNode) { if (m_pScriptNodeArray && !pdfium::ContainsValue(*m_pScriptNodeArray, pNode)) m_pScriptNodeArray->push_back(pNode); } CXFA_Object* CFXJSE_Engine::ToXFAObject(v8::Local obj) { if (obj.IsEmpty() || !obj->IsObject()) return nullptr; CFXJSE_HostObject* pHostObj = FXJSE_RetrieveObjectBinding(obj.As()); return pHostObj ? pHostObj->AsCXFAObject() : nullptr; } v8::Local CFXJSE_Engine::NewXFAObject( CXFA_Object* obj, v8::Global& tmpl) { v8::EscapableHandleScope scope(GetIsolate()); v8::Local klass = v8::Local::New(GetIsolate(), tmpl); v8::Local object = klass->InstanceTemplate() ->NewInstance(m_JsContext->GetContext()) .ToLocalChecked(); FXJSE_UpdateObjectBinding(object, obj); return scope.Escape(object); }