diff options
Diffstat (limited to 'fxjs/xfa/cjx_tree.cpp')
-rw-r--r-- | fxjs/xfa/cjx_tree.cpp | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/fxjs/xfa/cjx_tree.cpp b/fxjs/xfa/cjx_tree.cpp new file mode 100644 index 0000000000..69cbfa0652 --- /dev/null +++ b/fxjs/xfa/cjx_tree.cpp @@ -0,0 +1,230 @@ +// Copyright 2017 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/xfa/cjx_tree.h" + +#include "fxjs/cfxjse_arguments.h" +#include "fxjs/cfxjse_engine.h" +#include "fxjs/cfxjse_value.h" +#include "third_party/base/ptr_util.h" +#include "xfa/fxfa/parser/cxfa_arraynodelist.h" +#include "xfa/fxfa/parser/cxfa_attachnodelist.h" +#include "xfa/fxfa/parser/cxfa_document.h" +#include "xfa/fxfa/parser/cxfa_node.h" +#include "xfa/fxfa/parser/cxfa_object.h" +#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" + +const CJX_MethodSpec CJX_Tree::MethodSpecs[] = { + {"resolveNode", resolveNode_static}, + {"resolveNodes", resolveNodes_static}, + {"", nullptr}}; + +CJX_Tree::CJX_Tree(CXFA_Object* obj) : CJX_Object(obj) { + DefineMethods(MethodSpecs); +} + +CJX_Tree::~CJX_Tree() {} + +void CJX_Tree::resolveNode(CFXJSE_Arguments* pArguments) { + int32_t iLength = pArguments->GetLength(); + if (iLength != 1) { + ThrowParamCountMismatchException(L"resolveNode"); + return; + } + WideString wsExpression = + WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringView()); + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return; + CXFA_Object* refNode = GetXFAObject(); + if (refNode->GetElementType() == XFA_Element::Xfa) + refNode = pScriptContext->GetThisObject(); + uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | + XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings; + XFA_RESOLVENODE_RS resolveNodeRS; + if (!pScriptContext->ResolveObjects(ToNode(refNode), + wsExpression.AsStringView(), + &resolveNodeRS, dwFlag, nullptr)) { + pArguments->GetReturnValue()->SetNull(); + return; + } + if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { + CXFA_Object* pObject = resolveNodeRS.objects.front(); + pArguments->GetReturnValue()->Assign( + pScriptContext->GetJSValueFromMap(pObject)); + } else { + const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo = + resolveNodeRS.pScriptAttribute; + if (lpAttributeInfo && + lpAttributeInfo->eValueType == XFA_ScriptType::Object) { + auto pValue = + pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetRuntime()); + CJX_Object* jsObject = resolveNodeRS.objects.front()->JSObject(); + (jsObject->*(lpAttributeInfo->callback))(pValue.get(), false, + lpAttributeInfo->attribute); + pArguments->GetReturnValue()->Assign(pValue.get()); + } else { + pArguments->GetReturnValue()->SetNull(); + } + } +} + +void CJX_Tree::resolveNodes(CFXJSE_Arguments* pArguments) { + int32_t iLength = pArguments->GetLength(); + if (iLength != 1) { + ThrowParamCountMismatchException(L"resolveNodes"); + return; + } + + WideString wsExpression = + WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringView()); + CFXJSE_Value* pValue = pArguments->GetReturnValue(); + if (!pValue) + return; + + CXFA_Object* refNode = GetXFAObject(); + if (refNode->GetElementType() == XFA_Element::Xfa) + refNode = GetDocument()->GetScriptContext()->GetThisObject(); + + ResolveNodeList(pValue, wsExpression, + XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes | + XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent | + XFA_RESOLVENODE_Siblings, + ToNode(refNode)); +} + +void CJX_Tree::all(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + uint32_t dwFlag = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL; + WideString wsExpression = GetAttribute(XFA_Attribute::Name) + L"[*]"; + ResolveNodeList(pValue, wsExpression, dwFlag, nullptr); +} + +void CJX_Tree::classAll(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + WideString wsExpression = L"#" + GetXFAObject()->GetClassName() + L"[*]"; + ResolveNodeList(pValue, wsExpression, + XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL, nullptr); +} + +void CJX_Tree::nodes(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return; + + if (bSetting) { + WideString wsMessage = L"Unable to set "; + FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView()); + return; + } + + CXFA_AttachNodeList* pNodeList = + new CXFA_AttachNodeList(GetDocument(), ToNode(GetXFAObject())); + pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass()); +} + +void CJX_Tree::parent(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + CXFA_Node* pParent = ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_Parent); + if (!pParent) { + pValue->SetNull(); + return; + } + + pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pParent)); +} + +void CJX_Tree::index(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameNameIndex()); +} + +void CJX_Tree::classIndex(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameClassIndex()); +} + +void CJX_Tree::somExpression(CFXJSE_Value* pValue, + bool bSetting, + XFA_Attribute eAttribute) { + if (bSetting) { + ThrowInvalidPropertyException(); + return; + } + + WideString wsSOMExpression; + GetXFAObject()->GetSOMExpression(wsSOMExpression); + pValue->SetString(wsSOMExpression.UTF8Encode().AsStringView()); +} + +void CJX_Tree::ResolveNodeList(CFXJSE_Value* pValue, + WideString wsExpression, + uint32_t dwFlag, + CXFA_Node* refNode) { + CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext(); + if (!pScriptContext) + return; + if (!refNode) + refNode = ToNode(GetXFAObject()); + + XFA_RESOLVENODE_RS resolveNodeRS; + pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(), + &resolveNodeRS, dwFlag, nullptr); + CXFA_ArrayNodeList* pNodeList = new CXFA_ArrayNodeList(GetDocument()); + if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) { + for (CXFA_Object* pObject : resolveNodeRS.objects) { + if (pObject->IsNode()) + pNodeList->Append(pObject->AsNode()); + } + } else { + if (resolveNodeRS.pScriptAttribute && + resolveNodeRS.pScriptAttribute->eValueType == XFA_ScriptType::Object) { + for (CXFA_Object* pObject : resolveNodeRS.objects) { + auto pValue = + pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetRuntime()); + CJX_Object* jsObject = pObject->JSObject(); + (jsObject->*(resolveNodeRS.pScriptAttribute->callback))( + pValue.get(), false, resolveNodeRS.pScriptAttribute->attribute); + + CXFA_Object* obj = CFXJSE_Engine::ToObject(pValue.get(), nullptr); + if (obj->IsNode()) + pNodeList->Append(obj->AsNode()); + } + } + } + pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass()); +} |