Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cjx_instancemanager.cpp
Go to the documentation of this file.
1// Copyright 2017 The PDFium Authors
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/xfa/cjx_instancemanager.h"
8
9#include <algorithm>
10#include <vector>
11
12#include "fxjs/fxv8.h"
13#include "fxjs/js_resources.h"
14#include "fxjs/xfa/cfxjse_engine.h"
15#include "third_party/base/check_op.h"
16#include "third_party/base/containers/span.h"
17#include "v8/include/v8-object.h"
18#include "v8/include/v8-primitive.h"
19#include "xfa/fxfa/cxfa_ffdoc.h"
20#include "xfa/fxfa/cxfa_ffnotify.h"
21#include "xfa/fxfa/parser/cxfa_document.h"
22#include "xfa/fxfa/parser/cxfa_instancemanager.h"
23#include "xfa/fxfa/parser/cxfa_occur.h"
24#include "xfa/fxfa/parser/cxfa_subform.h"
25
26const CJX_MethodSpec CJX_InstanceManager::MethodSpecs[] = {
27 {"addInstance", addInstance_static},
28 {"insertInstance", insertInstance_static},
29 {"moveInstance", moveInstance_static},
30 {"removeInstance", removeInstance_static},
31 {"setInstances", setInstances_static}};
32
33CJX_InstanceManager::CJX_InstanceManager(CXFA_InstanceManager* mgr)
34 : CJX_Node(mgr) {
35 DefineMethods(MethodSpecs);
36}
37
38CJX_InstanceManager::~CJX_InstanceManager() = default;
39
40bool CJX_InstanceManager::DynamicTypeIs(TypeTag eType) const {
41 return eType == static_type__ || ParentType__::DynamicTypeIs(eType);
42}
43
44int32_t CJX_InstanceManager::SetInstances(v8::Isolate* pIsolate,
45 int32_t iDesired) {
46 CXFA_Occur* occur = GetXFANode()->GetOccurIfExists();
47 int32_t iMin = occur ? occur->GetMin() : CXFA_Occur::kDefaultMin;
48 if (iDesired < iMin) {
49 ThrowTooManyOccurrencesException(pIsolate, L"min");
50 return 1;
51 }
52
53 int32_t iMax = occur ? occur->GetMax() : CXFA_Occur::kDefaultMax;
54 if (iMax >= 0 && iDesired > iMax) {
55 ThrowTooManyOccurrencesException(pIsolate, L"max");
56 return 2;
57 }
58
59 int32_t iCount = GetXFANode()->GetCount();
60 if (iDesired == iCount)
61 return 0;
62
63 if (iDesired < iCount) {
64 WideString wsInstManagerName = GetCData(XFA_Attribute::Name);
65 WideString wsInstanceName = WideString(
66 wsInstManagerName.IsEmpty()
67 ? wsInstManagerName
68 : wsInstManagerName.Last(wsInstManagerName.GetLength() - 1));
69 uint32_t dInstanceNameHash =
70 FX_HashCode_GetW(wsInstanceName.AsStringView());
71 CXFA_Node* pPrevSibling = iDesired == 0
72 ? GetXFANode()
73 : GetXFANode()->GetItemIfExists(iDesired - 1);
74 if (!pPrevSibling) {
75 // TODO(dsinclair): Better error?
77 return 0;
78 }
79
80 while (iCount > iDesired) {
81 CXFA_Node* pRemoveInstance = pPrevSibling->GetNextSibling();
82 const XFA_Element type = pRemoveInstance->GetElementType();
83 if (type != XFA_Element::Subform && type != XFA_Element::SubformSet) {
84 continue;
85 }
86 CHECK_NE(type, XFA_Element::InstanceManager);
87 if (pRemoveInstance->GetNameHash() == dInstanceNameHash) {
88 GetXFANode()->RemoveItem(pRemoveInstance, true);
89 iCount--;
90 }
91 }
92 } else {
93 while (iCount < iDesired) {
94 CXFA_Node* pNewInstance = GetXFANode()->CreateInstanceIfPossible(true);
95 if (!pNewInstance)
96 return 0;
97
98 GetXFANode()->InsertItem(pNewInstance, iCount, iCount, false);
99 ++iCount;
100
101 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
102 if (!pNotify)
103 return 0;
104
105 pNotify->RunNodeInitialize(pNewInstance);
106 }
107 }
108 GetDocument()->GetLayoutProcessor()->SetHasChangedContainer();
109 return 0;
110}
111
112int32_t CJX_InstanceManager::MoveInstance(v8::Isolate* pIsolate,
113 int32_t iTo,
114 int32_t iFrom) {
115 int32_t iCount = GetXFANode()->GetCount();
116 if (iFrom > iCount || iTo > iCount - 1) {
118 return 1;
119 }
120 if (iFrom < 0 || iTo < 0 || iFrom == iTo)
121 return 0;
122
123 CXFA_Node* pMoveInstance = GetXFANode()->GetItemIfExists(iFrom);
124 if (!pMoveInstance) {
126 return 1;
127 }
128
129 GetXFANode()->RemoveItem(pMoveInstance, false);
130 GetXFANode()->InsertItem(pMoveInstance, iTo, iCount - 1, true);
131 GetDocument()->GetLayoutProcessor()->SetHasChangedContainer();
132 return 0;
133}
134
135CJS_Result CJX_InstanceManager::moveInstance(
136 CFXJSE_Engine* runtime,
137 pdfium::span<v8::Local<v8::Value>> params) {
138 CXFA_Document* doc = runtime->GetDocument();
141
142 if (params.size() != 2)
144
145 int32_t iFrom = runtime->ToInt32(params[0]);
146 int32_t iTo = runtime->ToInt32(params[1]);
147 MoveInstance(runtime->GetIsolate(), iTo, iFrom);
148
149 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
150 if (!pNotify)
152
153 CXFA_Node* pXFA = GetXFANode();
154 auto* pToInstance = CXFA_Subform::FromNode(pXFA->GetItemIfExists(iTo));
155 if (pToInstance)
156 pNotify->RunSubformIndexChange(pToInstance);
157
158 auto* pFromInstance = CXFA_Subform::FromNode(pXFA->GetItemIfExists(iFrom));
159 if (pFromInstance)
160 pNotify->RunSubformIndexChange(pFromInstance);
161
163}
164
165CJS_Result CJX_InstanceManager::removeInstance(
166 CFXJSE_Engine* runtime,
167 pdfium::span<v8::Local<v8::Value>> params) {
168 CXFA_Document* doc = runtime->GetDocument();
171
172 if (params.size() != 1)
174
175 int32_t iIndex = runtime->ToInt32(params[0]);
176 int32_t iCount = GetXFANode()->GetCount();
177 if (iIndex < 0 || iIndex >= iCount)
179
180 CXFA_Occur* occur = GetXFANode()->GetOccurIfExists();
181 int32_t iMin = occur ? occur->GetMin() : CXFA_Occur::kDefaultMin;
182 if (iCount - 1 < iMin)
184
185 CXFA_Node* pRemoveInstance = GetXFANode()->GetItemIfExists(iIndex);
186 if (!pRemoveInstance)
188
189 GetXFANode()->RemoveItem(pRemoveInstance, true);
190
191 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
192 if (pNotify) {
193 CXFA_Node* pXFA = GetXFANode();
194 for (int32_t i = iIndex; i < iCount - 1; i++) {
195 auto* pSubformInstance = CXFA_Subform::FromNode(pXFA->GetItemIfExists(i));
196 if (pSubformInstance)
197 pNotify->RunSubformIndexChange(pSubformInstance);
198 }
199 }
200 GetDocument()->GetLayoutProcessor()->SetHasChangedContainer();
202}
203
204CJS_Result CJX_InstanceManager::setInstances(
205 CFXJSE_Engine* runtime,
206 pdfium::span<v8::Local<v8::Value>> params) {
207 CXFA_Document* doc = runtime->GetDocument();
210
211 if (params.size() != 1)
213
214 SetInstances(runtime->GetIsolate(), runtime->ToInt32(params[0]));
216}
217
218CJS_Result CJX_InstanceManager::addInstance(
219 CFXJSE_Engine* runtime,
220 pdfium::span<v8::Local<v8::Value>> params) {
221 CXFA_Document* doc = runtime->GetDocument();
224
225 if (!params.empty() && params.size() != 1)
227
228 bool fFlags = true;
229 if (params.size() == 1)
230 fFlags = runtime->ToBoolean(params[0]);
231
232 int32_t iCount = GetXFANode()->GetCount();
233 CXFA_Occur* occur = GetXFANode()->GetOccurIfExists();
234 int32_t iMax = occur ? occur->GetMax() : CXFA_Occur::kDefaultMax;
235 if (iMax >= 0 && iCount >= iMax)
237
238 CXFA_Node* pNewInstance = GetXFANode()->CreateInstanceIfPossible(fFlags);
239 if (!pNewInstance)
240 return CJS_Result::Success(runtime->NewNull());
241
242 GetXFANode()->InsertItem(pNewInstance, iCount, iCount, false);
243
244 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
245 if (pNotify) {
246 pNotify->RunNodeInitialize(pNewInstance);
247 GetDocument()->GetLayoutProcessor()->SetHasChangedContainer();
248 }
249
251 runtime->GetOrCreateJSBindingFromMap(pNewInstance));
252}
253
254CJS_Result CJX_InstanceManager::insertInstance(
255 CFXJSE_Engine* runtime,
256 pdfium::span<v8::Local<v8::Value>> params) {
257 CXFA_Document* doc = runtime->GetDocument();
260
261 if (params.size() != 1 && params.size() != 2)
263
264 int32_t iIndex = runtime->ToInt32(params[0]);
265 bool bBind = false;
266 if (params.size() == 2)
267 bBind = runtime->ToBoolean(params[1]);
268
269 int32_t iCount = GetXFANode()->GetCount();
270 if (iIndex < 0 || iIndex > iCount)
272
273 CXFA_Occur* occur = GetXFANode()->GetOccurIfExists();
274 int32_t iMax = occur ? occur->GetMax() : CXFA_Occur::kDefaultMax;
275 if (iMax >= 0 && iCount >= iMax)
277
278 CXFA_Node* pNewInstance = GetXFANode()->CreateInstanceIfPossible(bBind);
279 if (!pNewInstance)
280 return CJS_Result::Success(runtime->NewNull());
281
282 GetXFANode()->InsertItem(pNewInstance, iIndex, iCount, true);
283
284 CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
285 if (pNotify) {
286 pNotify->RunNodeInitialize(pNewInstance);
287 GetDocument()->GetLayoutProcessor()->SetHasChangedContainer();
288 }
289
291 runtime->GetOrCreateJSBindingFromMap(pNewInstance));
292}
293
294void CJX_InstanceManager::max(v8::Isolate* pIsolate,
295 v8::Local<v8::Value>* pValue,
296 bool bSetting,
297 XFA_Attribute eAttribute) {
298 if (bSetting) {
300 return;
301 }
302 CXFA_Occur* occur = GetXFANode()->GetOccurIfExists();
303 *pValue = fxv8::NewNumberHelper(
304 pIsolate, occur ? occur->GetMax() : CXFA_Occur::kDefaultMax);
305}
306
307void CJX_InstanceManager::min(v8::Isolate* pIsolate,
308 v8::Local<v8::Value>* pValue,
309 bool bSetting,
310 XFA_Attribute eAttribute) {
311 if (bSetting) {
313 return;
314 }
315 CXFA_Occur* occur = GetXFANode()->GetOccurIfExists();
316 *pValue = fxv8::NewNumberHelper(
317 pIsolate, occur ? occur->GetMin() : CXFA_Occur::kDefaultMin);
318}
319
320void CJX_InstanceManager::count(v8::Isolate* pIsolate,
321 v8::Local<v8::Value>* pValue,
322 bool bSetting,
323 XFA_Attribute eAttribute) {
324 if (bSetting) {
325 SetInstances(pIsolate, fxv8::ReentrantToInt32Helper(pIsolate, *pValue));
326 return;
327 }
328 *pValue = fxv8::NewNumberHelper(pIsolate, GetXFANode()->GetCount());
329}
friend class EventParamScope
CXFA_Document * GetDocument() const
static CJS_Result Success()
Definition cjs_result.h:27
static CJS_Result Failure(JSMessage id)
Definition cjs_result.h:34
int32_t MoveInstance(v8::Isolate *pIsolate, int32_t iTo, int32_t iFrom)
~CJX_InstanceManager() override
bool DynamicTypeIs(TypeTag eType) const override
bool DynamicTypeIs(TypeTag eType) const override
Definition cjx_node.cpp:112
void DefineMethods(pdfium::span< const CJX_MethodSpec > methods)
void ThrowIndexOutOfBoundsException(v8::Isolate *pIsolate) const
void ThrowInvalidPropertyException(v8::Isolate *pIsolate) const
CXFA_Document * GetDocument() const
WideString GetCData(XFA_Attribute eAttr) const
CXFA_Node * GetXFANode() const
void ThrowTooManyOccurrencesException(v8::Isolate *pIsolate, const WideString &obj) const
FormType GetFormType() const
void RunNodeInitialize(CXFA_Node *pNode)
void RunSubformIndexChange(CXFA_Subform *pSubformNode)
uint32_t GetNameHash() const
Definition cxfa_node.h:190
CXFA_Node * GetItemIfExists(int32_t iIndex)
XFA_Element GetElementType() const
Definition cxfa_object.h:91
static constexpr int32_t kDefaultMax
Definition cxfa_occur.h:16
static constexpr int32_t kDefaultMin
Definition cxfa_occur.h:17
int32_t GetMax()
int32_t GetMin()
static CXFA_Subform * FromNode(CXFA_Node *pNode)
bool IsEmpty() const
Definition widestring.h:118
FormType
Definition fxfa.h:38
XFA_Attribute
Definition fxfa_basic.h:67
XFA_Element
Definition fxfa_basic.h:75
JSMessage
@ kNotSupportedError
@ kTooManyOccurrences
@ kInvalidInputError