• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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_document_datamerger_imp.h"
8 
9 #include <map>
10 #include <vector>
11 
12 #include "core/fxcrt/fx_extension.h"
13 #include "core/fxcrt/xml/cfx_xmlelement.h"
14 #include "core/fxcrt/xml/cfx_xmlnode.h"
15 #include "fxjs/cfxjse_engine.h"
16 #include "fxjs/xfa/cjx_object.h"
17 #include "third_party/base/logging.h"
18 #include "third_party/base/stl_util.h"
19 #include "xfa/fxfa/parser/cxfa_bind.h"
20 #include "xfa/fxfa/parser/cxfa_datagroup.h"
21 #include "xfa/fxfa/parser/cxfa_document.h"
22 #include "xfa/fxfa/parser/cxfa_exdata.h"
23 #include "xfa/fxfa/parser/cxfa_form.h"
24 #include "xfa/fxfa/parser/cxfa_image.h"
25 #include "xfa/fxfa/parser/cxfa_items.h"
26 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
27 #include "xfa/fxfa/parser/cxfa_localemgr.h"
28 #include "xfa/fxfa/parser/cxfa_node.h"
29 #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
30 #include "xfa/fxfa/parser/cxfa_occur.h"
31 #include "xfa/fxfa/parser/cxfa_pageset.h"
32 #include "xfa/fxfa/parser/cxfa_subform.h"
33 #include "xfa/fxfa/parser/cxfa_template.h"
34 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h"
35 #include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
36 #include "xfa/fxfa/parser/cxfa_value.h"
37 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
38 #include "xfa/fxfa/parser/xfa_utils.h"
39 
40 namespace {
41 
42 class CXFA_TraverseStrategy_DDGroup {
43  public:
GetFirstChild(CXFA_Node * pDDGroupNode)44   static CXFA_Node* GetFirstChild(CXFA_Node* pDDGroupNode) {
45     return pDDGroupNode->GetFirstChildByName(XFA_HASHCODE_Group);
46   }
GetNextSibling(CXFA_Node * pDDGroupNode)47   static CXFA_Node* GetNextSibling(CXFA_Node* pDDGroupNode) {
48     return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group);
49   }
GetParent(CXFA_Node * pDDGroupNode)50   static CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) {
51     return pDDGroupNode->GetParent();
52   }
53 };
54 
55 struct RecurseRecord {
56   CXFA_Node* pTemplateChild;
57   CXFA_Node* pDataChild;
58 };
59 
FormValueNode_CreateChild(CXFA_Node * pValueNode,XFA_Element iType)60 CXFA_Node* FormValueNode_CreateChild(CXFA_Node* pValueNode, XFA_Element iType) {
61   CXFA_Node* pChildNode = pValueNode->GetFirstChild();
62   if (!pChildNode) {
63     if (iType == XFA_Element::Unknown)
64       return nullptr;
65 
66     pChildNode =
67         pValueNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, iType);
68   }
69   return pChildNode;
70 }
71 
FormValueNode_MatchNoneCreateChild(CXFA_Node * pFormNode)72 void FormValueNode_MatchNoneCreateChild(CXFA_Node* pFormNode) {
73   CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
74   ASSERT(pWidgetAcc);
75   pWidgetAcc->GetUIType();
76 }
77 
FormValueNode_SetChildContent(CXFA_Node * pValueNode,const WideString & wsContent,XFA_Element iType=XFA_Element::Unknown)78 bool FormValueNode_SetChildContent(CXFA_Node* pValueNode,
79                                    const WideString& wsContent,
80                                    XFA_Element iType = XFA_Element::Unknown) {
81   if (!pValueNode)
82     return false;
83 
84   ASSERT(pValueNode->GetPacketType() == XFA_PacketType::Form);
85   CXFA_Node* pChildNode = FormValueNode_CreateChild(pValueNode, iType);
86   if (!pChildNode)
87     return false;
88 
89   switch (pChildNode->GetObjectType()) {
90     case XFA_ObjectType::ContentNode: {
91       CXFA_Node* pContentRawDataNode = pChildNode->GetFirstChild();
92       if (!pContentRawDataNode) {
93         XFA_Element element = XFA_Element::Sharptext;
94         if (pChildNode->GetElementType() == XFA_Element::ExData) {
95           Optional<WideString> contentType =
96               pChildNode->JSObject()->TryAttribute(XFA_Attribute::ContentType,
97                                                    false);
98           if (contentType) {
99             if (*contentType == L"text/html")
100               element = XFA_Element::SharpxHTML;
101             else if (*contentType == L"text/xml")
102               element = XFA_Element::Sharpxml;
103           }
104         }
105         pContentRawDataNode = pChildNode->CreateSamePacketNode(element);
106         pChildNode->InsertChild(pContentRawDataNode, nullptr);
107       }
108       pContentRawDataNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
109                                                 false, false);
110       break;
111     }
112     case XFA_ObjectType::NodeC:
113     case XFA_ObjectType::TextNode:
114     case XFA_ObjectType::NodeV: {
115       pChildNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent, false,
116                                        false);
117       break;
118     }
119     default:
120       NOTREACHED();
121       break;
122   }
123   return true;
124 }
125 
CreateDataBinding(CXFA_Node * pFormNode,CXFA_Node * pDataNode,bool bDataToForm)126 void CreateDataBinding(CXFA_Node* pFormNode,
127                        CXFA_Node* pDataNode,
128                        bool bDataToForm) {
129   pFormNode->SetBindingNode(pDataNode);
130   pDataNode->AddBindItem(pFormNode);
131   XFA_Element eType = pFormNode->GetElementType();
132   if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
133     return;
134 
135   CXFA_WidgetAcc* pWidgetAcc = pFormNode->GetWidgetAcc();
136   ASSERT(pWidgetAcc);
137   XFA_Element eUIType = pWidgetAcc->GetUIType();
138   auto* defValue = pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
139       0, XFA_Element::Value);
140   if (!bDataToForm) {
141     WideString wsValue;
142     switch (eUIType) {
143       case XFA_Element::ImageEdit: {
144         CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
145         WideString wsContentType;
146         WideString wsHref;
147         if (image) {
148           wsValue = image->GetContent();
149           wsContentType = image->GetContentType();
150           wsHref = image->GetHref();
151         }
152         CFX_XMLElement* pXMLDataElement =
153             static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode());
154         ASSERT(pXMLDataElement);
155 
156         pDataNode->JSObject()->SetAttributeValue(
157             wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
158         pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
159                                         wsContentType, false, false);
160         if (!wsHref.IsEmpty())
161           pXMLDataElement->SetString(L"href", wsHref);
162 
163         break;
164       }
165       case XFA_Element::ChoiceList:
166         wsValue = defValue ? defValue->GetChildValueContent() : L"";
167         if (pWidgetAcc->IsChoiceListMultiSelect()) {
168           std::vector<WideString> wsSelTextArray =
169               pWidgetAcc->GetSelectedItemsValue();
170           if (!wsSelTextArray.empty()) {
171             for (const auto& text : wsSelTextArray) {
172               CXFA_Node* pValue =
173                   pDataNode->CreateSamePacketNode(XFA_Element::DataValue);
174               pValue->JSObject()->SetCData(XFA_Attribute::Name, L"value", false,
175                                            false);
176               pValue->CreateXMLMappingNode();
177               pDataNode->InsertChild(pValue, nullptr);
178               pValue->JSObject()->SetCData(XFA_Attribute::Value, text, false,
179                                            false);
180             }
181           } else {
182             CFX_XMLNode* pXMLNode = pDataNode->GetXMLMappingNode();
183             ASSERT(pXMLNode->GetType() == FX_XMLNODE_Element);
184             static_cast<CFX_XMLElement*>(pXMLNode)->SetString(L"xfa:dataNode",
185                                                               L"dataGroup");
186           }
187         } else if (!wsValue.IsEmpty()) {
188           pDataNode->JSObject()->SetAttributeValue(
189               wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
190         }
191         break;
192       case XFA_Element::CheckButton:
193         wsValue = defValue ? defValue->GetChildValueContent() : L"";
194         if (wsValue.IsEmpty())
195           break;
196 
197         pDataNode->JSObject()->SetAttributeValue(
198             wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
199         break;
200       case XFA_Element::ExclGroup: {
201         CXFA_Node* pChecked = nullptr;
202         CXFA_Node* pChild = pFormNode->GetFirstChild();
203         for (; pChild; pChild = pChild->GetNextSibling()) {
204           if (pChild->GetElementType() != XFA_Element::Field)
205             continue;
206 
207           auto* pValue =
208               pChild->GetChild<CXFA_Value>(0, XFA_Element::Value, false);
209           if (!pValue)
210             continue;
211 
212           wsValue = pValue->GetChildValueContent();
213           if (wsValue.IsEmpty())
214             continue;
215 
216           CXFA_Items* pItems =
217               pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
218           if (!pItems)
219             continue;
220 
221           CXFA_Node* pText = pItems->GetFirstChild();
222           if (!pText)
223             continue;
224 
225           WideString wsContent = pText->JSObject()->GetContent(false);
226           if (wsContent == wsValue) {
227             pChecked = pChild;
228             pDataNode->JSObject()->SetAttributeValue(wsValue, wsValue, false,
229                                                      false);
230             pFormNode->JSObject()->SetCData(XFA_Attribute::Value, wsContent,
231                                             false, false);
232             break;
233           }
234         }
235         if (!pChecked)
236           break;
237 
238         pChild = pFormNode->GetFirstChild();
239         for (; pChild; pChild = pChild->GetNextSibling()) {
240           if (pChild == pChecked)
241             continue;
242           if (pChild->GetElementType() != XFA_Element::Field)
243             continue;
244 
245           CXFA_Value* pValue =
246               pChild->JSObject()->GetOrCreateProperty<CXFA_Value>(
247                   0, XFA_Element::Value);
248           CXFA_Items* pItems =
249               pChild->GetChild<CXFA_Items>(0, XFA_Element::Items, false);
250           CXFA_Node* pText = pItems ? pItems->GetFirstChild() : nullptr;
251           if (pText)
252             pText = pText->GetNextSibling();
253 
254           WideString wsContent;
255           if (pText)
256             wsContent = pText->JSObject()->GetContent(false);
257 
258           FormValueNode_SetChildContent(pValue, wsContent, XFA_Element::Text);
259         }
260         break;
261       }
262       case XFA_Element::NumericEdit: {
263         wsValue = defValue ? defValue->GetChildValueContent() : L"";
264         if (wsValue.IsEmpty())
265           break;
266 
267         wsValue = pWidgetAcc->NormalizeNumStr(wsValue);
268         pDataNode->JSObject()->SetAttributeValue(
269             wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
270         CXFA_Value* pValue =
271             pFormNode->JSObject()->GetOrCreateProperty<CXFA_Value>(
272                 0, XFA_Element::Value);
273         FormValueNode_SetChildContent(pValue, wsValue, XFA_Element::Float);
274         break;
275       }
276       default:
277         wsValue = defValue ? defValue->GetChildValueContent() : L"";
278         if (wsValue.IsEmpty())
279           break;
280 
281         pDataNode->JSObject()->SetAttributeValue(
282             wsValue, pWidgetAcc->GetFormatDataValue(wsValue), false, false);
283         break;
284     }
285     return;
286   }
287 
288   WideString wsXMLValue = pDataNode->JSObject()->GetContent(false);
289   WideString wsNormalizeValue = pWidgetAcc->GetNormalizeDataValue(wsXMLValue);
290 
291   pDataNode->JSObject()->SetAttributeValue(wsNormalizeValue, wsXMLValue, false,
292                                            false);
293   switch (eUIType) {
294     case XFA_Element::ImageEdit: {
295       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
296                                     XFA_Element::Image);
297       CXFA_Image* image = defValue ? defValue->GetImageIfExists() : nullptr;
298       if (image) {
299         CFX_XMLElement* pXMLDataElement =
300             static_cast<CFX_XMLElement*>(pDataNode->GetXMLMappingNode());
301         ASSERT(pXMLDataElement);
302 
303         WideString wsContentType =
304             pXMLDataElement->GetString(L"xfa:contentType");
305         if (!wsContentType.IsEmpty()) {
306           pDataNode->JSObject()->SetCData(XFA_Attribute::ContentType,
307                                           wsContentType, false, false);
308           image->SetContentType(wsContentType);
309         }
310 
311         WideString wsHref = pXMLDataElement->GetString(L"href");
312         if (!wsHref.IsEmpty())
313           image->SetHref(wsHref);
314       }
315       break;
316     }
317     case XFA_Element::ChoiceList:
318       if (pWidgetAcc->IsChoiceListMultiSelect()) {
319         std::vector<CXFA_Node*> items = pDataNode->GetNodeList(
320             XFA_NODEFILTER_Children | XFA_NODEFILTER_Properties,
321             XFA_Element::Unknown);
322         if (!items.empty()) {
323           bool single = items.size() == 1;
324           wsNormalizeValue.clear();
325 
326           for (CXFA_Node* pNode : items) {
327             WideString wsItem = pNode->JSObject()->GetContent(false);
328             if (single)
329               wsItem += L"\n";
330 
331             wsNormalizeValue += wsItem;
332           }
333           CXFA_ExData* exData =
334               defValue ? defValue->GetExDataIfExists() : nullptr;
335           ASSERT(exData);
336 
337           exData->SetContentType(single ? L"text/plain" : L"text/xml");
338         }
339         FormValueNode_SetChildContent(defValue, wsNormalizeValue,
340                                       XFA_Element::ExData);
341       } else {
342         FormValueNode_SetChildContent(defValue, wsNormalizeValue,
343                                       XFA_Element::Text);
344       }
345       break;
346     case XFA_Element::CheckButton:
347       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
348                                     XFA_Element::Text);
349       break;
350     case XFA_Element::ExclGroup: {
351       pWidgetAcc->SetSelectedMemberByValue(wsNormalizeValue.AsStringView(),
352                                            false, false, false);
353       break;
354     }
355     case XFA_Element::DateTimeEdit:
356       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
357                                     XFA_Element::DateTime);
358       break;
359     case XFA_Element::NumericEdit: {
360       WideString wsPicture =
361           pWidgetAcc->GetPictureContent(XFA_VALUEPICTURE_DataBind);
362       if (wsPicture.IsEmpty())
363         wsNormalizeValue = pWidgetAcc->NormalizeNumStr(wsNormalizeValue);
364 
365       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
366                                     XFA_Element::Float);
367       break;
368     }
369     case XFA_Element::Barcode:
370     case XFA_Element::Button:
371     case XFA_Element::PasswordEdit:
372     case XFA_Element::Signature:
373     case XFA_Element::TextEdit:
374     default:
375       FormValueNode_SetChildContent(defValue, wsNormalizeValue,
376                                     XFA_Element::Text);
377       break;
378   }
379 }
380 
GetGlobalBinding(CXFA_Document * pDocument,uint32_t dwNameHash)381 CXFA_Node* GetGlobalBinding(CXFA_Document* pDocument, uint32_t dwNameHash) {
382   auto it = pDocument->m_rgGlobalBinding.find(dwNameHash);
383   return it != pDocument->m_rgGlobalBinding.end() ? it->second : nullptr;
384 }
385 
RegisterGlobalBinding(CXFA_Document * pDocument,uint32_t dwNameHash,CXFA_Node * pDataNode)386 void RegisterGlobalBinding(CXFA_Document* pDocument,
387                            uint32_t dwNameHash,
388                            CXFA_Node* pDataNode) {
389   pDocument->m_rgGlobalBinding[dwNameHash] = pDataNode;
390 }
391 
ScopeMatchGlobalBinding(CXFA_Node * pDataScope,uint32_t dwNameHash,XFA_Element eMatchDataNodeType,bool bUpLevel)392 CXFA_Node* ScopeMatchGlobalBinding(CXFA_Node* pDataScope,
393                                    uint32_t dwNameHash,
394                                    XFA_Element eMatchDataNodeType,
395                                    bool bUpLevel) {
396   for (CXFA_Node *pCurDataScope = pDataScope, *pLastDataScope = nullptr;
397        pCurDataScope &&
398        pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
399        pLastDataScope = pCurDataScope,
400                  pCurDataScope = pCurDataScope->GetParent()) {
401     for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
402          pDataChild;
403          pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
404       if (pDataChild == pLastDataScope ||
405           (eMatchDataNodeType != XFA_Element::DataModel &&
406            pDataChild->GetElementType() != eMatchDataNodeType) ||
407           pDataChild->HasBindItem()) {
408         continue;
409       }
410       return pDataChild;
411     }
412 
413     for (CXFA_DataGroup* pDataChild =
414              pCurDataScope->GetFirstChildByClass<CXFA_DataGroup>(
415                  XFA_Element::DataGroup);
416          pDataChild;
417          pDataChild = pDataChild->GetNextSameClassSibling<CXFA_DataGroup>(
418              XFA_Element::DataGroup)) {
419       CXFA_Node* pDataNode = ScopeMatchGlobalBinding(pDataChild, dwNameHash,
420                                                      eMatchDataNodeType, false);
421       if (pDataNode)
422         return pDataNode;
423     }
424     if (!bUpLevel)
425       break;
426   }
427   return nullptr;
428 }
429 
FindGlobalDataNode(CXFA_Document * pDocument,const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)430 CXFA_Node* FindGlobalDataNode(CXFA_Document* pDocument,
431                               const WideString& wsName,
432                               CXFA_Node* pDataScope,
433                               XFA_Element eMatchNodeType) {
434   if (wsName.IsEmpty())
435     return nullptr;
436 
437   uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
438   CXFA_Node* pBounded = GetGlobalBinding(pDocument, dwNameHash);
439   if (!pBounded) {
440     pBounded =
441         ScopeMatchGlobalBinding(pDataScope, dwNameHash, eMatchNodeType, true);
442     if (pBounded)
443       RegisterGlobalBinding(pDocument, dwNameHash, pBounded);
444   }
445   return pBounded;
446 }
447 
FindOnceDataNode(CXFA_Document * pDocument,const WideString & wsName,CXFA_Node * pDataScope,XFA_Element eMatchNodeType)448 CXFA_Node* FindOnceDataNode(CXFA_Document* pDocument,
449                             const WideString& wsName,
450                             CXFA_Node* pDataScope,
451                             XFA_Element eMatchNodeType) {
452   if (wsName.IsEmpty())
453     return nullptr;
454 
455   uint32_t dwNameHash = FX_HashCode_GetW(wsName.AsStringView(), false);
456   CXFA_Node* pLastDataScope = nullptr;
457   for (CXFA_Node* pCurDataScope = pDataScope;
458        pCurDataScope &&
459        pCurDataScope->GetPacketType() == XFA_PacketType::Datasets;
460        pCurDataScope = pCurDataScope->GetParent()) {
461     for (CXFA_Node* pDataChild = pCurDataScope->GetFirstChildByName(dwNameHash);
462          pDataChild;
463          pDataChild = pDataChild->GetNextSameNameSibling(dwNameHash)) {
464       if (pDataChild == pLastDataScope || pDataChild->HasBindItem() ||
465           (eMatchNodeType != XFA_Element::DataModel &&
466            pDataChild->GetElementType() != eMatchNodeType)) {
467         continue;
468       }
469       return pDataChild;
470     }
471     pLastDataScope = pCurDataScope;
472   }
473   return nullptr;
474 }
475 
FindDataRefDataNode(CXFA_Document * pDocument,const WideString & wsRef,CXFA_Node * pDataScope,XFA_Element eMatchNodeType,CXFA_Node * pTemplateNode,bool bForceBind,bool bUpLevel)476 CXFA_Node* FindDataRefDataNode(CXFA_Document* pDocument,
477                                const WideString& wsRef,
478                                CXFA_Node* pDataScope,
479                                XFA_Element eMatchNodeType,
480                                CXFA_Node* pTemplateNode,
481                                bool bForceBind,
482                                bool bUpLevel) {
483   uint32_t dFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_BindNew;
484   if (bUpLevel || wsRef != L"name")
485     dFlags |= (XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings);
486 
487   XFA_RESOLVENODE_RS rs;
488   pDocument->GetScriptContext()->ResolveObjects(
489       pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
490   if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeAll ||
491       rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeMidAll ||
492       rs.objects.size() > 1) {
493     return pDocument->GetNotBindNode(rs.objects);
494   }
495 
496   if (rs.dwFlags == XFA_ResolveNode_RSType_CreateNodeOne) {
497     CXFA_Object* pObject = !rs.objects.empty() ? rs.objects.front() : nullptr;
498     CXFA_Node* pNode = ToNode(pObject);
499     return (bForceBind || !pNode || !pNode->HasBindItem()) ? pNode : nullptr;
500   }
501   return nullptr;
502 }
503 
NeedGenerateForm(CXFA_Node * pTemplateChild,bool bUseInstanceManager)504 bool NeedGenerateForm(CXFA_Node* pTemplateChild, bool bUseInstanceManager) {
505   XFA_Element eType = pTemplateChild->GetElementType();
506   if (eType == XFA_Element::Variables)
507     return true;
508   if (pTemplateChild->IsContainerNode())
509     return false;
510   if (eType == XFA_Element::Proto ||
511       (bUseInstanceManager && eType == XFA_Element::Occur)) {
512     return false;
513   }
514   return true;
515 }
516 
CloneOrMergeInstanceManager(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,std::vector<CXFA_Node * > * subforms)517 CXFA_Node* CloneOrMergeInstanceManager(CXFA_Document* pDocument,
518                                        CXFA_Node* pFormParent,
519                                        CXFA_Node* pTemplateNode,
520                                        std::vector<CXFA_Node*>* subforms) {
521   WideString wsSubformName =
522       pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
523   WideString wsInstMgrNodeName = L"_" + wsSubformName;
524   uint32_t dwInstNameHash =
525       FX_HashCode_GetW(wsInstMgrNodeName.AsStringView(), false);
526   CXFA_Node* pExistingNode = XFA_DataMerge_FindFormDOMInstance(
527       pDocument, XFA_Element::InstanceManager, dwInstNameHash, pFormParent);
528   if (pExistingNode) {
529     uint32_t dwNameHash = pTemplateNode->GetNameHash();
530     for (CXFA_Node* pNode = pExistingNode->GetNextSibling(); pNode;) {
531       XFA_Element eCurType = pNode->GetElementType();
532       if (eCurType == XFA_Element::InstanceManager)
533         break;
534 
535       if ((eCurType != XFA_Element::Subform) &&
536           (eCurType != XFA_Element::SubformSet)) {
537         pNode = pNode->GetNextSibling();
538         continue;
539       }
540       if (dwNameHash != pNode->GetNameHash())
541         break;
542 
543       CXFA_Node* pNextNode = pNode->GetNextSibling();
544       pFormParent->RemoveChild(pNode, true);
545       subforms->push_back(pNode);
546       pNode = pNextNode;
547     }
548     pFormParent->RemoveChild(pExistingNode, true);
549     pFormParent->InsertChild(pExistingNode, nullptr);
550     pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
551     pExistingNode->SetTemplateNode(pTemplateNode);
552     return pExistingNode;
553   }
554 
555   CXFA_Node* pNewNode =
556       pDocument->CreateNode(XFA_PacketType::Form, XFA_Element::InstanceManager);
557   wsInstMgrNodeName =
558       L"_" + pTemplateNode->JSObject()->GetCData(XFA_Attribute::Name);
559   pNewNode->JSObject()->SetCData(XFA_Attribute::Name, wsInstMgrNodeName, false,
560                                  false);
561   pFormParent->InsertChild(pNewNode, nullptr);
562   pNewNode->SetTemplateNode(pTemplateNode);
563   return pNewNode;
564 }
565 
FindMatchingDataNode(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pDataScope,bool & bAccessedDataDOM,bool bForceBind,CXFA_NodeIteratorTemplate<CXFA_Node,CXFA_TraverseStrategy_XFAContainerNode> * pIterator,bool & bSelfMatch,XFA_AttributeEnum & eBindMatch,bool bUpLevel)566 CXFA_Node* FindMatchingDataNode(
567     CXFA_Document* pDocument,
568     CXFA_Node* pTemplateNode,
569     CXFA_Node* pDataScope,
570     bool& bAccessedDataDOM,
571     bool bForceBind,
572     CXFA_NodeIteratorTemplate<CXFA_Node,
573                               CXFA_TraverseStrategy_XFAContainerNode>*
574         pIterator,
575     bool& bSelfMatch,
576     XFA_AttributeEnum& eBindMatch,
577     bool bUpLevel) {
578   CXFA_Node* pResult = nullptr;
579   CXFA_Node* pCurTemplateNode = pIterator->GetCurrent();
580   while (pCurTemplateNode) {
581     XFA_Element eMatchNodeType;
582     switch (pCurTemplateNode->GetElementType()) {
583       case XFA_Element::Subform:
584         eMatchNodeType = XFA_Element::DataGroup;
585         break;
586       case XFA_Element::Field: {
587         eMatchNodeType = XFA_FieldIsMultiListBox(pCurTemplateNode)
588                              ? XFA_Element::DataGroup
589                              : XFA_Element::DataValue;
590       } break;
591       case XFA_Element::ExclGroup:
592         eMatchNodeType = XFA_Element::DataValue;
593         break;
594       default:
595         pCurTemplateNode = pIterator->MoveToNext();
596         continue;
597     }
598 
599     CXFA_Occur* pTemplateNodeOccur =
600         pCurTemplateNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
601     if (pTemplateNodeOccur) {
602       int32_t iMin;
603       int32_t iMax;
604       int32_t iInit;
605       std::tie(iMin, iMax, iInit) = pTemplateNodeOccur->GetOccurInfo();
606       if (iMax == 0) {
607         pCurTemplateNode = pIterator->MoveToNext();
608         continue;
609       }
610     }
611 
612     CXFA_Bind* pTemplateNodeBind =
613         pCurTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind);
614     XFA_AttributeEnum eMatch =
615         pTemplateNodeBind
616             ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
617             : XFA_AttributeEnum::Once;
618     eBindMatch = eMatch;
619     switch (eMatch) {
620       case XFA_AttributeEnum::None:
621         pCurTemplateNode = pIterator->MoveToNext();
622         continue;
623       case XFA_AttributeEnum::Global:
624         bAccessedDataDOM = true;
625         if (!bForceBind) {
626           pCurTemplateNode = pIterator->MoveToNext();
627           continue;
628         }
629         if (eMatchNodeType == XFA_Element::DataValue ||
630             (eMatchNodeType == XFA_Element::DataGroup &&
631              XFA_FieldIsMultiListBox(pTemplateNodeBind))) {
632           CXFA_Node* pGlobalBindNode = FindGlobalDataNode(
633               pDocument,
634               pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
635               pDataScope, eMatchNodeType);
636           if (!pGlobalBindNode) {
637             pCurTemplateNode = pIterator->MoveToNext();
638             continue;
639           }
640           pResult = pGlobalBindNode;
641           break;
642         }
643       case XFA_AttributeEnum::Once: {
644         bAccessedDataDOM = true;
645         CXFA_Node* pOnceBindNode = FindOnceDataNode(
646             pDocument,
647             pCurTemplateNode->JSObject()->GetCData(XFA_Attribute::Name),
648             pDataScope, eMatchNodeType);
649         if (!pOnceBindNode) {
650           pCurTemplateNode = pIterator->MoveToNext();
651           continue;
652         }
653         pResult = pOnceBindNode;
654         break;
655       }
656       case XFA_AttributeEnum::DataRef: {
657         bAccessedDataDOM = true;
658         CXFA_Node* pDataRefBindNode = FindDataRefDataNode(
659             pDocument,
660             pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref),
661             pDataScope, eMatchNodeType, pTemplateNode, bForceBind, bUpLevel);
662         if (pDataRefBindNode &&
663             pDataRefBindNode->GetElementType() == eMatchNodeType) {
664           pResult = pDataRefBindNode;
665         }
666         if (!pResult) {
667           pCurTemplateNode = pIterator->SkipChildrenAndMoveToNext();
668           continue;
669         }
670         break;
671       }
672       default:
673         break;
674     }
675     if (pCurTemplateNode == pTemplateNode && pResult)
676       bSelfMatch = true;
677     break;
678   }
679   return pResult;
680 }
681 
SortRecurseRecord(std::vector<RecurseRecord> * rgRecords,CXFA_Node * pDataScope,bool bChoiceMode)682 void SortRecurseRecord(std::vector<RecurseRecord>* rgRecords,
683                        CXFA_Node* pDataScope,
684                        bool bChoiceMode) {
685   std::vector<RecurseRecord> rgResultRecord;
686   for (CXFA_Node* pNode = pDataScope->GetFirstChild(); pNode;
687        pNode = pNode->GetNextSibling()) {
688     auto it = std::find_if(rgRecords->begin(), rgRecords->end(),
689                            [pNode](const RecurseRecord& record) {
690                              return pNode == record.pDataChild;
691                            });
692     if (it != rgRecords->end()) {
693       rgResultRecord.push_back(*it);
694       rgRecords->erase(it);
695       if (bChoiceMode)
696         break;
697     }
698   }
699   if (rgResultRecord.empty())
700     return;
701 
702   if (!bChoiceMode) {
703     rgResultRecord.insert(rgResultRecord.end(), rgRecords->begin(),
704                           rgRecords->end());
705   }
706   *rgRecords = rgResultRecord;
707 }
708 
CopyContainer_SubformSet(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormParentNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge)709 CXFA_Node* CopyContainer_SubformSet(CXFA_Document* pDocument,
710                                     CXFA_Node* pTemplateNode,
711                                     CXFA_Node* pFormParentNode,
712                                     CXFA_Node* pDataScope,
713                                     bool bOneInstance,
714                                     bool bDataMerge) {
715   XFA_Element eType = pTemplateNode->GetElementType();
716   CXFA_Node* pOccurNode = nullptr;
717   CXFA_Node* pFirstInstance = nullptr;
718   bool bUseInstanceManager =
719       pFormParentNode->GetElementType() != XFA_Element::Area;
720   CXFA_Node* pInstMgrNode = nullptr;
721   std::vector<CXFA_Node*> subformArray;
722   std::vector<CXFA_Node*>* pSearchArray = nullptr;
723   if (!bOneInstance &&
724       (eType == XFA_Element::SubformSet || eType == XFA_Element::Subform)) {
725     pInstMgrNode = bUseInstanceManager ? CloneOrMergeInstanceManager(
726                                              pDocument, pFormParentNode,
727                                              pTemplateNode, &subformArray)
728                                        : nullptr;
729     if (CXFA_Occur* pOccurTemplateNode =
730             pTemplateNode->GetFirstChildByClass<CXFA_Occur>(
731                 XFA_Element::Occur)) {
732       pOccurNode = pInstMgrNode ? XFA_NodeMerge_CloneOrMergeContainer(
733                                       pDocument, pInstMgrNode,
734                                       pOccurTemplateNode, false, nullptr)
735                                 : pOccurTemplateNode;
736     } else if (pInstMgrNode) {
737       pOccurNode =
738           pInstMgrNode->GetFirstChildByClass<CXFA_Occur>(XFA_Element::Occur);
739       if (pOccurNode)
740         pOccurNode->ClearFlag(XFA_NodeFlag_UnusedNode);
741     }
742     if (pInstMgrNode) {
743       pInstMgrNode->SetFlag(XFA_NodeFlag_Initialized, true);
744       pSearchArray = &subformArray;
745       if (pFormParentNode->GetElementType() == XFA_Element::PageArea) {
746         bOneInstance = true;
747         if (subformArray.empty())
748           pSearchArray = nullptr;
749       } else if (pTemplateNode->GetNameHash() == 0 && subformArray.empty()) {
750         pSearchArray = nullptr;
751       }
752     }
753   }
754 
755   int32_t iMax = 1;
756   int32_t iInit = 1;
757   int32_t iMin = 1;
758   if (!bOneInstance && pOccurNode) {
759     std::tie(iMin, iMax, iInit) =
760         static_cast<CXFA_Occur*>(pOccurNode)->GetOccurInfo();
761   }
762 
763   XFA_AttributeEnum eRelation =
764       eType == XFA_Element::SubformSet
765           ? pTemplateNode->JSObject()->GetEnum(XFA_Attribute::Relation)
766           : XFA_AttributeEnum::Ordered;
767   int32_t iCurRepeatIndex = 0;
768   XFA_AttributeEnum eParentBindMatch = XFA_AttributeEnum::None;
769   if (bDataMerge) {
770     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
771         sNodeIterator(pTemplateNode);
772     bool bAccessedDataDOM = false;
773     if (eType == XFA_Element::SubformSet || eType == XFA_Element::Area) {
774       sNodeIterator.MoveToNext();
775     } else {
776       std::map<CXFA_Node*, CXFA_Node*> subformMapArray;
777       std::vector<CXFA_Node*> nodeArray;
778       for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
779         bool bSelfMatch = false;
780         XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None;
781         CXFA_Node* pDataNode = FindMatchingDataNode(
782             pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, false,
783             &sNodeIterator, bSelfMatch, eBindMatch, true);
784         if (!pDataNode || sNodeIterator.GetCurrent() != pTemplateNode)
785           break;
786 
787         eParentBindMatch = eBindMatch;
788         CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
789             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
790         if (!pFirstInstance)
791           pFirstInstance = pSubformNode;
792 
793         CreateDataBinding(pSubformNode, pDataNode, true);
794         ASSERT(pSubformNode);
795         subformMapArray[pSubformNode] = pDataNode;
796         nodeArray.push_back(pSubformNode);
797       }
798 
799       for (CXFA_Node* pSubform : nodeArray) {
800         CXFA_Node* pDataNode = nullptr;
801         auto it = subformMapArray.find(pSubform);
802         if (it != subformMapArray.end())
803           pDataNode = it->second;
804         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
805              pTemplateChild;
806              pTemplateChild = pTemplateChild->GetNextSibling()) {
807           if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
808             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubform,
809                                                 pTemplateChild, true, nullptr);
810           } else if (pTemplateChild->IsContainerNode()) {
811             pDocument->DataMerge_CopyContainer(pTemplateChild, pSubform,
812                                                pDataNode, false, true, false);
813           }
814         }
815       }
816       subformMapArray.clear();
817     }
818 
819     for (; iMax < 0 || iCurRepeatIndex < iMax; iCurRepeatIndex++) {
820       bool bSelfMatch = false;
821       XFA_AttributeEnum eBindMatch = XFA_AttributeEnum::None;
822       if (!FindMatchingDataNode(pDocument, pTemplateNode, pDataScope,
823                                 bAccessedDataDOM, false, &sNodeIterator,
824                                 bSelfMatch, eBindMatch, true)) {
825         break;
826       }
827       if (eBindMatch == XFA_AttributeEnum::DataRef &&
828           eParentBindMatch == XFA_AttributeEnum::DataRef) {
829         break;
830       }
831 
832       if (eRelation == XFA_AttributeEnum::Choice ||
833           eRelation == XFA_AttributeEnum::Unordered) {
834         CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
835             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
836         ASSERT(pSubformSetNode);
837         if (!pFirstInstance)
838           pFirstInstance = pSubformSetNode;
839 
840         std::vector<RecurseRecord> rgItemMatchList;
841         std::vector<CXFA_Node*> rgItemUnmatchList;
842         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
843              pTemplateChild;
844              pTemplateChild = pTemplateChild->GetNextSibling()) {
845           if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
846             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
847                                                 pTemplateChild, true, nullptr);
848           } else if (pTemplateChild->IsContainerNode()) {
849             bSelfMatch = false;
850             eBindMatch = XFA_AttributeEnum::None;
851             if (eRelation != XFA_AttributeEnum::Ordered) {
852               CXFA_NodeIteratorTemplate<CXFA_Node,
853                                         CXFA_TraverseStrategy_XFAContainerNode>
854                   sChildIter(pTemplateChild);
855               CXFA_Node* pDataMatch = FindMatchingDataNode(
856                   pDocument, pTemplateChild, pDataScope, bAccessedDataDOM,
857                   false, &sChildIter, bSelfMatch, eBindMatch, true);
858               if (pDataMatch) {
859                 RecurseRecord sNewRecord = {pTemplateChild, pDataMatch};
860                 if (bSelfMatch)
861                   rgItemMatchList.insert(rgItemMatchList.begin(), sNewRecord);
862                 else
863                   rgItemMatchList.push_back(sNewRecord);
864               } else {
865                 rgItemUnmatchList.push_back(pTemplateChild);
866               }
867             } else {
868               rgItemUnmatchList.push_back(pTemplateChild);
869             }
870           }
871         }
872 
873         switch (eRelation) {
874           case XFA_AttributeEnum::Choice: {
875             ASSERT(!rgItemMatchList.empty());
876             SortRecurseRecord(&rgItemMatchList, pDataScope, true);
877             pDocument->DataMerge_CopyContainer(
878                 rgItemMatchList.front().pTemplateChild, pSubformSetNode,
879                 pDataScope, false, true, true);
880             break;
881           }
882           case XFA_AttributeEnum::Unordered: {
883             if (!rgItemMatchList.empty()) {
884               SortRecurseRecord(&rgItemMatchList, pDataScope, false);
885               for (const auto& matched : rgItemMatchList) {
886                 pDocument->DataMerge_CopyContainer(matched.pTemplateChild,
887                                                    pSubformSetNode, pDataScope,
888                                                    false, true, true);
889               }
890             }
891             for (auto* unmatched : rgItemUnmatchList) {
892               pDocument->DataMerge_CopyContainer(unmatched, pSubformSetNode,
893                                                  pDataScope, false, true, true);
894             }
895             break;
896           }
897           default:
898             break;
899         }
900       } else {
901         CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
902             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
903         ASSERT(pSubformSetNode);
904         if (!pFirstInstance)
905           pFirstInstance = pSubformSetNode;
906 
907         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
908              pTemplateChild;
909              pTemplateChild = pTemplateChild->GetNextSibling()) {
910           if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
911             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
912                                                 pTemplateChild, true, nullptr);
913           } else if (pTemplateChild->IsContainerNode()) {
914             pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
915                                                pDataScope, false, true, true);
916           }
917         }
918       }
919     }
920 
921     if (iCurRepeatIndex == 0 && bAccessedDataDOM == false) {
922       int32_t iLimit = iMax;
923       if (pInstMgrNode && pTemplateNode->GetNameHash() == 0) {
924         iLimit = pdfium::CollectionSize<int32_t>(subformArray);
925         if (iLimit < iMin)
926           iLimit = iInit;
927       }
928 
929       for (; (iLimit < 0 || iCurRepeatIndex < iLimit); iCurRepeatIndex++) {
930         if (pInstMgrNode) {
931           if (pSearchArray && pSearchArray->empty()) {
932             if (pTemplateNode->GetNameHash() != 0)
933               break;
934             pSearchArray = nullptr;
935           }
936         } else if (!XFA_DataMerge_FindFormDOMInstance(
937                        pDocument, pTemplateNode->GetElementType(),
938                        pTemplateNode->GetNameHash(), pFormParentNode)) {
939           break;
940         }
941         CXFA_Node* pSubformNode = XFA_NodeMerge_CloneOrMergeContainer(
942             pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
943         ASSERT(pSubformNode);
944         if (!pFirstInstance)
945           pFirstInstance = pSubformNode;
946 
947         for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
948              pTemplateChild;
949              pTemplateChild = pTemplateChild->GetNextSibling()) {
950           if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
951             XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformNode,
952                                                 pTemplateChild, true, nullptr);
953           } else if (pTemplateChild->IsContainerNode()) {
954             pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformNode,
955                                                pDataScope, false, true, true);
956           }
957         }
958       }
959     }
960   }
961 
962   int32_t iMinimalLimit = iCurRepeatIndex == 0 ? iInit : iMin;
963   for (; iCurRepeatIndex < iMinimalLimit; iCurRepeatIndex++) {
964     CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
965         pDocument, pFormParentNode, pTemplateNode, false, pSearchArray);
966     ASSERT(pSubformSetNode);
967     if (!pFirstInstance)
968       pFirstInstance = pSubformSetNode;
969 
970     bool bFound = false;
971     for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
972          pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
973       if (NeedGenerateForm(pTemplateChild, bUseInstanceManager)) {
974         XFA_NodeMerge_CloneOrMergeContainer(pDocument, pSubformSetNode,
975                                             pTemplateChild, true, nullptr);
976       } else if (pTemplateChild->IsContainerNode()) {
977         if (bFound && eRelation == XFA_AttributeEnum::Choice)
978           continue;
979 
980         pDocument->DataMerge_CopyContainer(pTemplateChild, pSubformSetNode,
981                                            pDataScope, false, bDataMerge, true);
982         bFound = true;
983       }
984     }
985   }
986   return pFirstInstance;
987 }
988 
CopyContainer_Field(CXFA_Document * pDocument,CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataMerge,bool bUpLevel)989 CXFA_Node* CopyContainer_Field(CXFA_Document* pDocument,
990                                CXFA_Node* pTemplateNode,
991                                CXFA_Node* pFormNode,
992                                CXFA_Node* pDataScope,
993                                bool bDataMerge,
994                                bool bUpLevel) {
995   CXFA_Node* pFieldNode = XFA_NodeMerge_CloneOrMergeContainer(
996       pDocument, pFormNode, pTemplateNode, false, nullptr);
997   ASSERT(pFieldNode);
998   for (CXFA_Node* pTemplateChildNode = pTemplateNode->GetFirstChild();
999        pTemplateChildNode;
1000        pTemplateChildNode = pTemplateChildNode->GetNextSibling()) {
1001     if (NeedGenerateForm(pTemplateChildNode, true)) {
1002       XFA_NodeMerge_CloneOrMergeContainer(pDocument, pFieldNode,
1003                                           pTemplateChildNode, true, nullptr);
1004     } else if (pTemplateNode->GetElementType() == XFA_Element::ExclGroup &&
1005                pTemplateChildNode->IsContainerNode()) {
1006       if (pTemplateChildNode->GetElementType() == XFA_Element::Field) {
1007         CopyContainer_Field(pDocument, pTemplateChildNode, pFieldNode, nullptr,
1008                             false, true);
1009       }
1010     }
1011   }
1012   if (bDataMerge) {
1013     bool bAccessedDataDOM = false;
1014     bool bSelfMatch = false;
1015     XFA_AttributeEnum eBindMatch;
1016     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFAContainerNode>
1017         sNodeIter(pTemplateNode);
1018     CXFA_Node* pDataNode = FindMatchingDataNode(
1019         pDocument, pTemplateNode, pDataScope, bAccessedDataDOM, true,
1020         &sNodeIter, bSelfMatch, eBindMatch, bUpLevel);
1021     if (pDataNode)
1022       CreateDataBinding(pFieldNode, pDataNode, true);
1023   } else {
1024     FormValueNode_MatchNoneCreateChild(pFieldNode);
1025   }
1026   return pFieldNode;
1027 }
1028 
MaybeCreateDataNode(CXFA_Document * pDocument,CXFA_Node * pDataParent,XFA_Element eNodeType,const WideString & wsName)1029 CXFA_Node* MaybeCreateDataNode(CXFA_Document* pDocument,
1030                                CXFA_Node* pDataParent,
1031                                XFA_Element eNodeType,
1032                                const WideString& wsName) {
1033   if (!pDataParent)
1034     return nullptr;
1035 
1036   CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode();
1037   if (!pParentDDNode) {
1038     CXFA_Node* pDataNode =
1039         pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
1040     pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false);
1041     pDataNode->CreateXMLMappingNode();
1042     pDataParent->InsertChild(pDataNode, nullptr);
1043     pDataNode->SetFlag(XFA_NodeFlag_Initialized, false);
1044     return pDataNode;
1045   }
1046 
1047   CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup> sIterator(
1048       pParentDDNode);
1049   for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
1050        pDDGroupNode = sIterator.MoveToNext()) {
1051     if (pDDGroupNode != pParentDDNode) {
1052       if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
1053         continue;
1054 
1055       Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
1056       if (!ns || *ns != L"http://ns.adobe.com/data-description/")
1057         continue;
1058     }
1059 
1060     CXFA_Node* pDDNode =
1061         pDDGroupNode->GetFirstChildByName(wsName.AsStringView());
1062     if (!pDDNode)
1063       continue;
1064     if (pDDNode->GetElementType() != eNodeType)
1065       break;
1066 
1067     CXFA_Node* pDataNode =
1068         pDocument->CreateNode(XFA_PacketType::Datasets, eNodeType);
1069     pDataNode->JSObject()->SetCData(XFA_Attribute::Name, wsName, false, false);
1070     pDataNode->CreateXMLMappingNode();
1071     if (eNodeType == XFA_Element::DataValue &&
1072         pDDNode->JSObject()->GetEnum(XFA_Attribute::Contains) ==
1073             XFA_AttributeEnum::MetaData) {
1074       pDataNode->JSObject()->SetEnum(XFA_Attribute::Contains,
1075                                      XFA_AttributeEnum::MetaData, false);
1076     }
1077     pDataParent->InsertChild(pDataNode, nullptr);
1078     pDataNode->SetDataDescriptionNode(pDDNode);
1079     pDataNode->SetFlag(XFA_NodeFlag_Initialized, false);
1080     return pDataNode;
1081   }
1082   return nullptr;
1083 }
1084 
UpdateBindingRelations(CXFA_Document * pDocument,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bDataRef,bool bParentDataRef)1085 void UpdateBindingRelations(CXFA_Document* pDocument,
1086                             CXFA_Node* pFormNode,
1087                             CXFA_Node* pDataScope,
1088                             bool bDataRef,
1089                             bool bParentDataRef) {
1090   bool bMatchRef = true;
1091   XFA_Element eType = pFormNode->GetElementType();
1092   CXFA_Node* pDataNode = pFormNode->GetBindData();
1093   if (eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup ||
1094       eType == XFA_Element::Field) {
1095     CXFA_Node* pTemplateNode = pFormNode->GetTemplateNodeIfExists();
1096     CXFA_Bind* pTemplateNodeBind =
1097         pTemplateNode
1098             ? pTemplateNode->GetFirstChildByClass<CXFA_Bind>(XFA_Element::Bind)
1099             : nullptr;
1100     XFA_AttributeEnum eMatch =
1101         pTemplateNodeBind
1102             ? pTemplateNodeBind->JSObject()->GetEnum(XFA_Attribute::Match)
1103             : XFA_AttributeEnum::Once;
1104     switch (eMatch) {
1105       case XFA_AttributeEnum::None:
1106         if (!bDataRef || bParentDataRef)
1107           FormValueNode_MatchNoneCreateChild(pFormNode);
1108         break;
1109       case XFA_AttributeEnum::Once:
1110         if (!bDataRef || bParentDataRef) {
1111           if (!pDataNode) {
1112             if (pFormNode->GetNameHash() != 0 &&
1113                 pFormNode->JSObject()->GetEnum(XFA_Attribute::Scope) !=
1114                     XFA_AttributeEnum::None) {
1115               XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1116                                            XFA_FieldIsMultiListBox(pFormNode))
1117                                               ? XFA_Element::DataGroup
1118                                               : XFA_Element::DataValue;
1119               pDataNode = MaybeCreateDataNode(
1120                   pDocument, pDataScope, eDataNodeType,
1121                   WideString(
1122                       pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1123               if (pDataNode)
1124                 CreateDataBinding(pFormNode, pDataNode, false);
1125             }
1126             if (!pDataNode)
1127               FormValueNode_MatchNoneCreateChild(pFormNode);
1128 
1129           } else {
1130             CXFA_Node* pDataParent = pDataNode->GetParent();
1131             if (pDataParent != pDataScope) {
1132               ASSERT(pDataParent);
1133               pDataParent->RemoveChild(pDataNode, true);
1134               pDataScope->InsertChild(pDataNode, nullptr);
1135             }
1136           }
1137         }
1138         break;
1139       case XFA_AttributeEnum::Global:
1140         if (!bDataRef || bParentDataRef) {
1141           uint32_t dwNameHash = pFormNode->GetNameHash();
1142           if (dwNameHash != 0 && !pDataNode) {
1143             pDataNode = GetGlobalBinding(pDocument, dwNameHash);
1144             if (!pDataNode) {
1145               XFA_Element eDataNodeType = (eType == XFA_Element::Subform ||
1146                                            XFA_FieldIsMultiListBox(pFormNode))
1147                                               ? XFA_Element::DataGroup
1148                                               : XFA_Element::DataValue;
1149               CXFA_Node* pRecordNode =
1150                   ToNode(pDocument->GetXFAObject(XFA_HASHCODE_Record));
1151               pDataNode = MaybeCreateDataNode(
1152                   pDocument, pRecordNode, eDataNodeType,
1153                   WideString(
1154                       pFormNode->JSObject()->GetCData(XFA_Attribute::Name)));
1155               if (pDataNode) {
1156                 CreateDataBinding(pFormNode, pDataNode, false);
1157                 RegisterGlobalBinding(pDocument, pFormNode->GetNameHash(),
1158                                       pDataNode);
1159               }
1160             } else {
1161               CreateDataBinding(pFormNode, pDataNode, true);
1162             }
1163           }
1164           if (!pDataNode)
1165             FormValueNode_MatchNoneCreateChild(pFormNode);
1166         }
1167         break;
1168       case XFA_AttributeEnum::DataRef: {
1169         bMatchRef = bDataRef;
1170         bParentDataRef = true;
1171         if (!pDataNode && bDataRef) {
1172           WideString wsRef =
1173               pTemplateNodeBind
1174                   ? pTemplateNodeBind->JSObject()->GetCData(XFA_Attribute::Ref)
1175                   : L"";
1176           uint32_t dFlags =
1177               XFA_RESOLVENODE_Children | XFA_RESOLVENODE_CreateNode;
1178           XFA_RESOLVENODE_RS rs;
1179           pDocument->GetScriptContext()->ResolveObjects(
1180               pDataScope, wsRef.AsStringView(), &rs, dFlags, pTemplateNode);
1181           CXFA_Object* pObject =
1182               !rs.objects.empty() ? rs.objects.front() : nullptr;
1183           pDataNode = ToNode(pObject);
1184           if (pDataNode) {
1185             CreateDataBinding(pFormNode, pDataNode,
1186                               rs.dwFlags == XFA_ResolveNode_RSType_ExistNodes);
1187           } else {
1188             FormValueNode_MatchNoneCreateChild(pFormNode);
1189           }
1190         }
1191         break;
1192       }
1193       default:
1194         break;
1195     }
1196   }
1197 
1198   if (bMatchRef &&
1199       (eType == XFA_Element::Subform || eType == XFA_Element::SubformSet ||
1200        eType == XFA_Element::Area || eType == XFA_Element::PageArea ||
1201        eType == XFA_Element::PageSet)) {
1202     for (CXFA_Node* pFormChild = pFormNode->GetFirstChild(); pFormChild;
1203          pFormChild = pFormChild->GetNextSibling()) {
1204       if (!pFormChild->IsContainerNode())
1205         continue;
1206       if (pFormChild->IsUnusedNode())
1207         continue;
1208 
1209       UpdateBindingRelations(pDocument, pFormChild,
1210                              pDataNode ? pDataNode : pDataScope, bDataRef,
1211                              bParentDataRef);
1212     }
1213   }
1214 }
1215 
UpdateDataRelation(CXFA_Node * pDataNode,CXFA_Node * pDataDescriptionNode)1216 void UpdateDataRelation(CXFA_Node* pDataNode, CXFA_Node* pDataDescriptionNode) {
1217   ASSERT(pDataDescriptionNode);
1218   for (CXFA_Node* pDataChild = pDataNode->GetFirstChild(); pDataChild;
1219        pDataChild = pDataChild->GetNextSibling()) {
1220     uint32_t dwNameHash = pDataChild->GetNameHash();
1221     if (!dwNameHash)
1222       continue;
1223 
1224     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup>
1225         sIterator(pDataDescriptionNode);
1226     for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
1227          pDDGroupNode = sIterator.MoveToNext()) {
1228       if (pDDGroupNode != pDataDescriptionNode) {
1229         if (pDDGroupNode->GetElementType() != XFA_Element::DataGroup)
1230           continue;
1231 
1232         Optional<WideString> ns = pDDGroupNode->JSObject()->TryNamespace();
1233         if (!ns || *ns != L"http://ns.adobe.com/data-description/")
1234           continue;
1235       }
1236 
1237       CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash);
1238       if (!pDDNode)
1239         continue;
1240       if (pDDNode->GetElementType() != pDataChild->GetElementType())
1241         break;
1242 
1243       pDataChild->SetDataDescriptionNode(pDDNode);
1244       UpdateDataRelation(pDataChild, pDDNode);
1245       break;
1246     }
1247   }
1248 }
1249 
1250 }  // namespace
1251 
XFA_DataMerge_FindFormDOMInstance(CXFA_Document * pDocument,XFA_Element eType,uint32_t dwNameHash,CXFA_Node * pFormParent)1252 CXFA_Node* XFA_DataMerge_FindFormDOMInstance(CXFA_Document* pDocument,
1253                                              XFA_Element eType,
1254                                              uint32_t dwNameHash,
1255                                              CXFA_Node* pFormParent) {
1256   CXFA_Node* pFormChild = pFormParent->GetFirstChild();
1257   for (; pFormChild; pFormChild = pFormChild->GetNextSibling()) {
1258     if (pFormChild->GetElementType() == eType &&
1259         pFormChild->GetNameHash() == dwNameHash && pFormChild->IsUnusedNode()) {
1260       return pFormChild;
1261     }
1262   }
1263   return nullptr;
1264 }
1265 
XFA_NodeMerge_CloneOrMergeContainer(CXFA_Document * pDocument,CXFA_Node * pFormParent,CXFA_Node * pTemplateNode,bool bRecursive,std::vector<CXFA_Node * > * pSubformArray)1266 CXFA_Node* XFA_NodeMerge_CloneOrMergeContainer(
1267     CXFA_Document* pDocument,
1268     CXFA_Node* pFormParent,
1269     CXFA_Node* pTemplateNode,
1270     bool bRecursive,
1271     std::vector<CXFA_Node*>* pSubformArray) {
1272   CXFA_Node* pExistingNode = nullptr;
1273   if (!pSubformArray) {
1274     pExistingNode = XFA_DataMerge_FindFormDOMInstance(
1275         pDocument, pTemplateNode->GetElementType(),
1276         pTemplateNode->GetNameHash(), pFormParent);
1277   } else if (!pSubformArray->empty()) {
1278     pExistingNode = pSubformArray->front();
1279     pSubformArray->erase(pSubformArray->begin());
1280   }
1281   if (pExistingNode) {
1282     if (pSubformArray) {
1283       pFormParent->InsertChild(pExistingNode, nullptr);
1284     } else if (pExistingNode->IsContainerNode()) {
1285       pFormParent->RemoveChild(pExistingNode, true);
1286       pFormParent->InsertChild(pExistingNode, nullptr);
1287     }
1288     pExistingNode->ClearFlag(XFA_NodeFlag_UnusedNode);
1289     pExistingNode->SetTemplateNode(pTemplateNode);
1290     if (bRecursive && pExistingNode->GetElementType() != XFA_Element::Items) {
1291       for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1292            pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1293         if (NeedGenerateForm(pTemplateChild, true)) {
1294           XFA_NodeMerge_CloneOrMergeContainer(
1295               pDocument, pExistingNode, pTemplateChild, bRecursive, nullptr);
1296         }
1297       }
1298     }
1299     pExistingNode->SetFlag(XFA_NodeFlag_Initialized, true);
1300     return pExistingNode;
1301   }
1302 
1303   CXFA_Node* pNewNode = pTemplateNode->CloneTemplateToForm(false);
1304   pFormParent->InsertChild(pNewNode, nullptr);
1305   if (bRecursive) {
1306     for (CXFA_Node* pTemplateChild = pTemplateNode->GetFirstChild();
1307          pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1308       if (NeedGenerateForm(pTemplateChild, true)) {
1309         CXFA_Node* pNewChild = pTemplateChild->CloneTemplateToForm(true);
1310         pNewNode->InsertChild(pNewChild, nullptr);
1311       }
1312     }
1313   }
1314   return pNewNode;
1315 }
1316 
XFA_DataMerge_FindDataScope(CXFA_Node * pParentFormNode)1317 CXFA_Node* XFA_DataMerge_FindDataScope(CXFA_Node* pParentFormNode) {
1318   for (CXFA_Node* pRootBoundNode = pParentFormNode;
1319        pRootBoundNode && pRootBoundNode->IsContainerNode();
1320        pRootBoundNode = pRootBoundNode->GetParent()) {
1321     CXFA_Node* pDataScope = pRootBoundNode->GetBindData();
1322     if (pDataScope)
1323       return pDataScope;
1324   }
1325   return ToNode(
1326       pParentFormNode->GetDocument()->GetXFAObject(XFA_HASHCODE_Data));
1327 }
1328 
DataMerge_CopyContainer(CXFA_Node * pTemplateNode,CXFA_Node * pFormNode,CXFA_Node * pDataScope,bool bOneInstance,bool bDataMerge,bool bUpLevel)1329 CXFA_Node* CXFA_Document::DataMerge_CopyContainer(CXFA_Node* pTemplateNode,
1330                                                   CXFA_Node* pFormNode,
1331                                                   CXFA_Node* pDataScope,
1332                                                   bool bOneInstance,
1333                                                   bool bDataMerge,
1334                                                   bool bUpLevel) {
1335   switch (pTemplateNode->GetElementType()) {
1336     case XFA_Element::SubformSet:
1337     case XFA_Element::Subform:
1338     case XFA_Element::Area:
1339     case XFA_Element::PageArea:
1340       return CopyContainer_SubformSet(this, pTemplateNode, pFormNode,
1341                                       pDataScope, bOneInstance, bDataMerge);
1342     case XFA_Element::ExclGroup:
1343     case XFA_Element::Field:
1344     case XFA_Element::Draw:
1345     case XFA_Element::ContentArea:
1346       return CopyContainer_Field(this, pTemplateNode, pFormNode, pDataScope,
1347                                  bDataMerge, bUpLevel);
1348     case XFA_Element::PageSet:
1349     case XFA_Element::Variables:
1350       break;
1351     default:
1352       NOTREACHED();
1353       break;
1354   }
1355   return nullptr;
1356 }
1357 
DataMerge_UpdateBindingRelations(CXFA_Node * pFormUpdateRoot)1358 void CXFA_Document::DataMerge_UpdateBindingRelations(
1359     CXFA_Node* pFormUpdateRoot) {
1360   CXFA_Node* pDataScope =
1361       XFA_DataMerge_FindDataScope(pFormUpdateRoot->GetParent());
1362   if (!pDataScope)
1363     return;
1364 
1365   UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, false, false);
1366   UpdateBindingRelations(this, pFormUpdateRoot, pDataScope, true, false);
1367 }
1368 
GetNotBindNode(const std::vector<CXFA_Object * > & arrayObjects)1369 CXFA_Node* CXFA_Document::GetNotBindNode(
1370     const std::vector<CXFA_Object*>& arrayObjects) {
1371   for (CXFA_Object* pObject : arrayObjects) {
1372     CXFA_Node* pNode = pObject->AsNode();
1373     if (pNode && !pNode->HasBindItem())
1374       return pNode;
1375   }
1376   return nullptr;
1377 }
1378 
DoDataMerge()1379 void CXFA_Document::DoDataMerge() {
1380   CXFA_Node* pDatasetsRoot = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
1381   if (!pDatasetsRoot) {
1382     CFX_XMLElement* pDatasetsXMLNode = new CFX_XMLElement(L"xfa:datasets");
1383     pDatasetsXMLNode->SetString(L"xmlns:xfa",
1384                                 L"http://www.xfa.org/schema/xfa-data/1.0/");
1385     pDatasetsRoot =
1386         CreateNode(XFA_PacketType::Datasets, XFA_Element::DataModel);
1387     pDatasetsRoot->JSObject()->SetCData(XFA_Attribute::Name, L"datasets", false,
1388                                         false);
1389     m_pRootNode->GetXMLMappingNode()->InsertChildNode(pDatasetsXMLNode);
1390     m_pRootNode->InsertChild(pDatasetsRoot, nullptr);
1391     pDatasetsRoot->SetXMLMappingNode(pDatasetsXMLNode);
1392   }
1393   CXFA_Node *pDataRoot = nullptr, *pDDRoot = nullptr;
1394   WideString wsDatasetsURI =
1395       pDatasetsRoot->JSObject()->TryNamespace().value_or(WideString());
1396   for (CXFA_Node* pChildNode = pDatasetsRoot->GetFirstChild(); pChildNode;
1397        pChildNode = pChildNode->GetNextSibling()) {
1398     if (pChildNode->GetElementType() != XFA_Element::DataGroup)
1399       continue;
1400 
1401     if (!pDDRoot && pChildNode->GetNameHash() == XFA_HASHCODE_DataDescription) {
1402       Optional<WideString> namespaceURI =
1403           pChildNode->JSObject()->TryNamespace();
1404       if (!namespaceURI)
1405         continue;
1406       if (*namespaceURI == L"http://ns.adobe.com/data-description/")
1407         pDDRoot = pChildNode;
1408     } else if (!pDataRoot && pChildNode->GetNameHash() == XFA_HASHCODE_Data) {
1409       Optional<WideString> namespaceURI =
1410           pChildNode->JSObject()->TryNamespace();
1411       if (!namespaceURI)
1412         continue;
1413       if (*namespaceURI == wsDatasetsURI)
1414         pDataRoot = pChildNode;
1415     }
1416     if (pDataRoot && pDDRoot)
1417       break;
1418   }
1419 
1420   if (!pDataRoot) {
1421     CFX_XMLElement* pDataRootXMLNode = new CFX_XMLElement(L"xfa:data");
1422     pDataRoot = CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup);
1423     pDataRoot->JSObject()->SetCData(XFA_Attribute::Name, L"data", false, false);
1424     pDataRoot->SetXMLMappingNode(pDataRootXMLNode);
1425     pDatasetsRoot->InsertChild(pDataRoot, nullptr);
1426   }
1427 
1428   CXFA_DataGroup* pDataTopLevel =
1429       pDataRoot->GetFirstChildByClass<CXFA_DataGroup>(XFA_Element::DataGroup);
1430   uint32_t dwNameHash = pDataTopLevel ? pDataTopLevel->GetNameHash() : 0;
1431   CXFA_Template* pTemplateRoot =
1432       m_pRootNode->GetFirstChildByClass<CXFA_Template>(XFA_Element::Template);
1433   if (!pTemplateRoot)
1434     return;
1435 
1436   CXFA_Node* pTemplateChosen =
1437       dwNameHash != 0 ? pTemplateRoot->GetFirstChildByName(dwNameHash)
1438                       : nullptr;
1439   if (!pTemplateChosen ||
1440       pTemplateChosen->GetElementType() != XFA_Element::Subform) {
1441     pTemplateChosen =
1442         pTemplateRoot->GetFirstChildByClass<CXFA_Subform>(XFA_Element::Subform);
1443   }
1444   if (!pTemplateChosen)
1445     return;
1446 
1447   CXFA_Form* pFormRoot =
1448       m_pRootNode->GetFirstChildByClass<CXFA_Form>(XFA_Element::Form);
1449   bool bEmptyForm = false;
1450   if (!pFormRoot) {
1451     bEmptyForm = true;
1452     pFormRoot = static_cast<CXFA_Form*>(
1453         CreateNode(XFA_PacketType::Form, XFA_Element::Form));
1454     ASSERT(pFormRoot);
1455     pFormRoot->JSObject()->SetCData(XFA_Attribute::Name, L"form", false, false);
1456     m_pRootNode->InsertChild(pFormRoot, nullptr);
1457   } else {
1458     CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode>
1459         sIterator(pFormRoot);
1460     for (CXFA_Node* pNode = sIterator.MoveToNext(); pNode;
1461          pNode = sIterator.MoveToNext()) {
1462       pNode->SetFlag(XFA_NodeFlag_UnusedNode, true);
1463     }
1464   }
1465 
1466   CXFA_Node* pSubformSetNode = XFA_NodeMerge_CloneOrMergeContainer(
1467       this, pFormRoot, pTemplateChosen, false, nullptr);
1468   ASSERT(pSubformSetNode);
1469   if (!pDataTopLevel) {
1470     WideString wsFormName =
1471         pSubformSetNode->JSObject()->GetCData(XFA_Attribute::Name);
1472     WideString wsDataTopLevelName(wsFormName.IsEmpty() ? L"form" : wsFormName);
1473     CFX_XMLElement* pDataTopLevelXMLNode =
1474         new CFX_XMLElement(wsDataTopLevelName);
1475 
1476     pDataTopLevel = static_cast<CXFA_DataGroup*>(
1477         CreateNode(XFA_PacketType::Datasets, XFA_Element::DataGroup));
1478     pDataTopLevel->JSObject()->SetCData(XFA_Attribute::Name, wsDataTopLevelName,
1479                                         false, false);
1480     pDataTopLevel->SetXMLMappingNode(pDataTopLevelXMLNode);
1481     CXFA_Node* pBeforeNode = pDataRoot->GetFirstChild();
1482     pDataRoot->InsertChild(pDataTopLevel, pBeforeNode);
1483   }
1484 
1485   ASSERT(pDataTopLevel);
1486   CreateDataBinding(pSubformSetNode, pDataTopLevel, true);
1487   for (CXFA_Node* pTemplateChild = pTemplateChosen->GetFirstChild();
1488        pTemplateChild; pTemplateChild = pTemplateChild->GetNextSibling()) {
1489     if (NeedGenerateForm(pTemplateChild, true)) {
1490       XFA_NodeMerge_CloneOrMergeContainer(this, pSubformSetNode, pTemplateChild,
1491                                           true, nullptr);
1492     } else if (pTemplateChild->IsContainerNode()) {
1493       DataMerge_CopyContainer(pTemplateChild, pSubformSetNode, pDataTopLevel,
1494                               false, true, true);
1495     }
1496   }
1497   if (pDDRoot)
1498     UpdateDataRelation(pDataRoot, pDDRoot);
1499 
1500   DataMerge_UpdateBindingRelations(pSubformSetNode);
1501   CXFA_PageSet* pPageSetNode =
1502       pSubformSetNode->GetFirstChildByClass<CXFA_PageSet>(XFA_Element::PageSet);
1503   while (pPageSetNode) {
1504     m_pPendingPageSet.push_back(pPageSetNode);
1505     CXFA_PageSet* pNextPageSetNode =
1506         pPageSetNode->GetNextSameClassSibling<CXFA_PageSet>(
1507             XFA_Element::PageSet);
1508     pSubformSetNode->RemoveChild(pPageSetNode, true);
1509     pPageSetNode = pNextPageSetNode;
1510   }
1511 
1512   if (bEmptyForm)
1513     return;
1514 
1515   CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_XFANode> sIterator(
1516       pFormRoot);
1517   CXFA_Node* pNode = sIterator.MoveToNext();
1518   while (pNode) {
1519     if (pNode->IsUnusedNode()) {
1520       if (pNode->IsContainerNode() ||
1521           pNode->GetElementType() == XFA_Element::InstanceManager) {
1522         CXFA_Node* pNext = sIterator.SkipChildrenAndMoveToNext();
1523         pNode->GetParent()->RemoveChild(pNode, true);
1524         pNode = pNext;
1525       } else {
1526         pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
1527         pNode->SetFlag(XFA_NodeFlag_Initialized, true);
1528         pNode = sIterator.MoveToNext();
1529       }
1530     } else {
1531       pNode->SetFlag(XFA_NodeFlag_Initialized, true);
1532       pNode = sIterator.MoveToNext();
1533     }
1534   }
1535 }
1536 
DoDataRemerge(bool bDoDataMerge)1537 void CXFA_Document::DoDataRemerge(bool bDoDataMerge) {
1538   CXFA_Node* pFormRoot = ToNode(GetXFAObject(XFA_HASHCODE_Form));
1539   if (pFormRoot) {
1540     while (CXFA_Node* pNode = pFormRoot->GetFirstChild())
1541       pFormRoot->RemoveChild(pNode, true);
1542 
1543     pFormRoot->SetBindingNode(nullptr);
1544   }
1545   m_rgGlobalBinding.clear();
1546 
1547   if (bDoDataMerge)
1548     DoDataMerge();
1549 
1550   CXFA_LayoutProcessor* pLayoutProcessor = GetLayoutProcessor();
1551   pLayoutProcessor->SetForceReLayout(true);
1552 }
1553