1// Copyright 2016 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/xfa_object.h"
8
9#include <memory>
10
11#include "core/fxcrt/fx_ext.h"
12#include "xfa/fxfa/parser/cxfa_document.h"
13#include "xfa/fxfa/parser/cxfa_scriptcontext.h"
14
15CXFA_NodeList::CXFA_NodeList(CXFA_Document* pDocument)
16    : CXFA_Object(pDocument,
17                  XFA_ObjectType::NodeList,
18                  XFA_Element::NodeList,
19                  CFX_WideStringC(L"nodeList")) {
20  m_pDocument->GetScriptContext()->AddToCacheList(
21      std::unique_ptr<CXFA_NodeList>(this));
22}
23
24CXFA_NodeList::~CXFA_NodeList() {}
25
26CXFA_Node* CXFA_NodeList::NamedItem(const CFX_WideStringC& wsName) {
27  uint32_t dwHashCode = FX_HashCode_GetW(wsName, false);
28  int32_t iCount = GetLength();
29  for (int32_t i = 0; i < iCount; i++) {
30    CXFA_Node* ret = Item(i);
31    if (dwHashCode == ret->GetNameHash())
32      return ret;
33  }
34  return nullptr;
35}
36
37void CXFA_NodeList::Script_ListClass_Append(CFXJSE_Arguments* pArguments) {
38  int32_t argc = pArguments->GetLength();
39  if (argc != 1) {
40    ThrowParamCountMismatchException(L"append");
41    return;
42  }
43
44  CXFA_Node* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
45  if (!pNode) {
46    ThrowArgumentMismatchException();
47    return;
48  }
49  Append(pNode);
50}
51
52void CXFA_NodeList::Script_ListClass_Insert(CFXJSE_Arguments* pArguments) {
53  int32_t argc = pArguments->GetLength();
54  if (argc != 2) {
55    ThrowParamCountMismatchException(L"insert");
56    return;
57  }
58
59  CXFA_Node* pNewNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
60  CXFA_Node* pBeforeNode = static_cast<CXFA_Node*>(pArguments->GetObject(1));
61  if (!pNewNode) {
62    ThrowArgumentMismatchException();
63    return;
64  }
65  Insert(pNewNode, pBeforeNode);
66}
67
68void CXFA_NodeList::Script_ListClass_Remove(CFXJSE_Arguments* pArguments) {
69  int32_t argc = pArguments->GetLength();
70  if (argc != 1) {
71    ThrowParamCountMismatchException(L"remove");
72    return;
73  }
74
75  CXFA_Node* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
76  if (!pNode) {
77    ThrowArgumentMismatchException();
78    return;
79  }
80  Remove(pNode);
81}
82
83void CXFA_NodeList::Script_ListClass_Item(CFXJSE_Arguments* pArguments) {
84  int32_t argc = pArguments->GetLength();
85  if (argc != 1) {
86    ThrowParamCountMismatchException(L"item");
87    return;
88  }
89
90  int32_t iIndex = pArguments->GetInt32(0);
91  if (iIndex < 0 || iIndex >= GetLength()) {
92    ThrowIndexOutOfBoundsException();
93    return;
94  }
95  pArguments->GetReturnValue()->Assign(
96      m_pDocument->GetScriptContext()->GetJSValueFromMap(Item(iIndex)));
97}
98
99void CXFA_NodeList::Script_TreelistClass_NamedItem(
100    CFXJSE_Arguments* pArguments) {
101  int32_t argc = pArguments->GetLength();
102  if (argc != 1) {
103    ThrowParamCountMismatchException(L"namedItem");
104    return;
105  }
106
107  CFX_ByteString szName = pArguments->GetUTF8String(0);
108  CXFA_Node* pNode =
109      NamedItem(CFX_WideString::FromUTF8(szName.AsStringC()).AsStringC());
110  if (!pNode)
111    return;
112
113  pArguments->GetReturnValue()->Assign(
114      m_pDocument->GetScriptContext()->GetJSValueFromMap(pNode));
115}
116
117void CXFA_NodeList::Script_ListClass_Length(CFXJSE_Value* pValue,
118                                            bool bSetting,
119                                            XFA_ATTRIBUTE eAttribute) {
120  if (bSetting) {
121    ThrowInvalidPropertyException();
122    return;
123  }
124  pValue->SetInteger(GetLength());
125}
126