// 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 <vector>
|
|
#include "fxjs/cfxjse_engine.h"
|
#include "fxjs/cfxjse_value.h"
|
#include "fxjs/js_resources.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}};
|
|
CJX_Tree::CJX_Tree(CXFA_Object* obj) : CJX_Object(obj) {
|
DefineMethods(MethodSpecs, FX_ArraySize(MethodSpecs));
|
}
|
|
CJX_Tree::~CJX_Tree() {}
|
|
CJS_Return CJX_Tree::resolveNode(
|
CJS_V8* runtime,
|
const std::vector<v8::Local<v8::Value>>& params) {
|
if (params.size() != 1)
|
return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
|
|
WideString expression = runtime->ToWideString(params[0]);
|
CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
|
if (!pScriptContext)
|
return CJS_Return(true);
|
|
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),
|
expression.AsStringView(), &resolveNodeRS,
|
dwFlag, nullptr)) {
|
return CJS_Return(runtime->NewNull());
|
}
|
|
if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
|
CXFA_Object* pObject = resolveNodeRS.objects.front();
|
CFXJSE_Value* value =
|
GetDocument()->GetScriptContext()->GetJSValueFromMap(pObject);
|
if (!value)
|
return CJS_Return(runtime->NewNull());
|
|
return CJS_Return(value->DirectGetValue().Get(runtime->GetIsolate()));
|
}
|
|
const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo =
|
resolveNodeRS.pScriptAttribute;
|
if (!lpAttributeInfo ||
|
lpAttributeInfo->eValueType != XFA_ScriptType::Object) {
|
return CJS_Return(runtime->NewNull());
|
}
|
|
auto pValue = pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetIsolate());
|
CJX_Object* jsObject = resolveNodeRS.objects.front()->JSObject();
|
(jsObject->*(lpAttributeInfo->callback))(pValue.get(), false,
|
lpAttributeInfo->attribute);
|
return CJS_Return(pValue->DirectGetValue().Get(runtime->GetIsolate()));
|
}
|
|
CJS_Return CJX_Tree::resolveNodes(
|
CJS_V8* runtime,
|
const std::vector<v8::Local<v8::Value>>& params) {
|
if (params.size() != 1)
|
return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
|
|
CXFA_Object* refNode = GetXFAObject();
|
if (refNode->GetElementType() == XFA_Element::Xfa)
|
refNode = GetDocument()->GetScriptContext()->GetThisObject();
|
|
CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
|
if (!pScriptContext)
|
return CJS_Return(true);
|
|
auto pValue = pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetIsolate());
|
ResolveNodeList(pValue.get(), runtime->ToWideString(params[0]),
|
XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
|
XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
|
XFA_RESOLVENODE_Siblings,
|
ToNode(refNode));
|
return CJS_Return(pValue->DirectGetValue().Get(runtime->GetIsolate()));
|
}
|
|
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::name(CFXJSE_Value* pValue,
|
bool bSetting,
|
XFA_Attribute eAttribute) {
|
Script_Attribute_String(pValue, bSetting, eAttribute);
|
}
|
|
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())->GetParent();
|
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();
|
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->GetIsolate());
|
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());
|
}
|