[xfa] Move JS method information to files.

This CL moves the XFA SOM JS Method information out of the c-array and
into individual CJX class files.

Change-Id: I401046a06aacaf1f04e5a51eb899e479de012e15
Reviewed-on: https://pdfium-review.googlesource.com/20450
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 0aa00e9..7a35526 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1192,6 +1192,7 @@
 
   if (pdf_enable_v8) {
     sources += [
+      "fxjs/CJX_Define.h",
       "fxjs/JS_Define.cpp",
       "fxjs/JS_Define.h",
       "fxjs/cjs_annot.cpp",
@@ -1318,8 +1319,6 @@
         "fxjs/cjx_logpseudomodel.h",
         "fxjs/cjx_node.cpp",
         "fxjs/cjx_node.h",
-        "fxjs/cjx_nodelist.cpp",
-        "fxjs/cjx_nodelist.h",
         "fxjs/cjx_object.cpp",
         "fxjs/cjx_object.h",
         "fxjs/cjx_signaturepseudomodel.cpp",
@@ -1327,6 +1326,44 @@
         "fxjs/cjx_thisproxy.cpp",
         "fxjs/cjx_thisproxy.h",
         "fxjs/fxjse.h",
+        "fxjs/xfa/cjx_container.cpp",
+        "fxjs/xfa/cjx_container.h",
+        "fxjs/xfa/cjx_content.cpp",
+        "fxjs/xfa/cjx_content.h",
+        "fxjs/xfa/cjx_delta.cpp",
+        "fxjs/xfa/cjx_delta.h",
+        "fxjs/xfa/cjx_desc.cpp",
+        "fxjs/xfa/cjx_desc.h",
+        "fxjs/xfa/cjx_exclgroup.cpp",
+        "fxjs/xfa/cjx_exclgroup.h",
+        "fxjs/xfa/cjx_field.cpp",
+        "fxjs/xfa/cjx_field.h",
+        "fxjs/xfa/cjx_form.cpp",
+        "fxjs/xfa/cjx_form.h",
+        "fxjs/xfa/cjx_instancemanager.cpp",
+        "fxjs/xfa/cjx_instancemanager.h",
+        "fxjs/xfa/cjx_list.cpp",
+        "fxjs/xfa/cjx_list.h",
+        "fxjs/xfa/cjx_manifest.cpp",
+        "fxjs/xfa/cjx_manifest.h",
+        "fxjs/xfa/cjx_model.cpp",
+        "fxjs/xfa/cjx_model.h",
+        "fxjs/xfa/cjx_packet.cpp",
+        "fxjs/xfa/cjx_packet.h",
+        "fxjs/xfa/cjx_source.cpp",
+        "fxjs/xfa/cjx_source.h",
+        "fxjs/xfa/cjx_subform.cpp",
+        "fxjs/xfa/cjx_subform.h",
+        "fxjs/xfa/cjx_template.cpp",
+        "fxjs/xfa/cjx_template.h",
+        "fxjs/xfa/cjx_textnode.cpp",
+        "fxjs/xfa/cjx_textnode.h",
+        "fxjs/xfa/cjx_tree.cpp",
+        "fxjs/xfa/cjx_tree.h",
+        "fxjs/xfa/cjx_treelist.cpp",
+        "fxjs/xfa/cjx_treelist.h",
+        "fxjs/xfa/cjx_wsdlconnection.cpp",
+        "fxjs/xfa/cjx_wsdlconnection.h",
       ]
     }
   } else {
@@ -1943,8 +1980,6 @@
       "xfa/fxfa/parser/cxfa_datamodel.h",
       "xfa/fxfa/parser/cxfa_datavalue.cpp",
       "xfa/fxfa/parser/cxfa_datavalue.h",
-      "xfa/fxfa/parser/cxfa_datawindow.cpp",
-      "xfa/fxfa/parser/cxfa_datawindow.h",
       "xfa/fxfa/parser/cxfa_date.cpp",
       "xfa/fxfa/parser/cxfa_date.h",
       "xfa/fxfa/parser/cxfa_datepattern.cpp",
@@ -2036,8 +2071,6 @@
       "xfa/fxfa/parser/cxfa_event.h",
       "xfa/fxfa/parser/cxfa_eventdata.cpp",
       "xfa/fxfa/parser/cxfa_eventdata.h",
-      "xfa/fxfa/parser/cxfa_eventpseudomodel.cpp",
-      "xfa/fxfa/parser/cxfa_eventpseudomodel.h",
       "xfa/fxfa/parser/cxfa_exclgroup.cpp",
       "xfa/fxfa/parser/cxfa_exclgroup.h",
       "xfa/fxfa/parser/cxfa_exclude.cpp",
@@ -2082,8 +2115,6 @@
       "xfa/fxfa/parser/cxfa_groupparent.h",
       "xfa/fxfa/parser/cxfa_handler.cpp",
       "xfa/fxfa/parser/cxfa_handler.h",
-      "xfa/fxfa/parser/cxfa_hostpseudomodel.cpp",
-      "xfa/fxfa/parser/cxfa_hostpseudomodel.h",
       "xfa/fxfa/parser/cxfa_hyphenation.cpp",
       "xfa/fxfa/parser/cxfa_hyphenation.h",
       "xfa/fxfa/parser/cxfa_ifempty.cpp",
@@ -2131,8 +2162,6 @@
       "xfa/fxfa/parser/cxfa_layoutpagemgr.h",
       "xfa/fxfa/parser/cxfa_layoutprocessor.cpp",
       "xfa/fxfa/parser/cxfa_layoutprocessor.h",
-      "xfa/fxfa/parser/cxfa_layoutpseudomodel.cpp",
-      "xfa/fxfa/parser/cxfa_layoutpseudomodel.h",
       "xfa/fxfa/parser/cxfa_level.cpp",
       "xfa/fxfa/parser/cxfa_level.h",
       "xfa/fxfa/parser/cxfa_line.cpp",
@@ -2157,8 +2186,6 @@
       "xfa/fxfa/parser/cxfa_lockdocument.h",
       "xfa/fxfa/parser/cxfa_log.cpp",
       "xfa/fxfa/parser/cxfa_log.h",
-      "xfa/fxfa/parser/cxfa_logpseudomodel.cpp",
-      "xfa/fxfa/parser/cxfa_logpseudomodel.h",
       "xfa/fxfa/parser/cxfa_manifest.cpp",
       "xfa/fxfa/parser/cxfa_manifest.h",
       "xfa/fxfa/parser/cxfa_map.cpp",
@@ -2203,8 +2230,6 @@
       "xfa/fxfa/parser/cxfa_nodehelper.cpp",
       "xfa/fxfa/parser/cxfa_nodehelper.h",
       "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h",
-      "xfa/fxfa/parser/cxfa_nodelist.cpp",
-      "xfa/fxfa/parser/cxfa_nodelist.h",
       "xfa/fxfa/parser/cxfa_nodelocale.cpp",
       "xfa/fxfa/parser/cxfa_nodelocale.h",
       "xfa/fxfa/parser/cxfa_numberofcopies.cpp",
@@ -2356,8 +2381,6 @@
       "xfa/fxfa/parser/cxfa_signature.h",
       "xfa/fxfa/parser/cxfa_signatureproperties.cpp",
       "xfa/fxfa/parser/cxfa_signatureproperties.h",
-      "xfa/fxfa/parser/cxfa_signaturepseudomodel.cpp",
-      "xfa/fxfa/parser/cxfa_signaturepseudomodel.h",
       "xfa/fxfa/parser/cxfa_signdata.cpp",
       "xfa/fxfa/parser/cxfa_signdata.h",
       "xfa/fxfa/parser/cxfa_signing.cpp",
@@ -2451,6 +2474,8 @@
       "xfa/fxfa/parser/cxfa_traversestrategy_layoutitem.h",
       "xfa/fxfa/parser/cxfa_traversestrategy_xfacontainernode.h",
       "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h",
+      "xfa/fxfa/parser/cxfa_treelist.cpp",
+      "xfa/fxfa/parser/cxfa_treelist.h",
       "xfa/fxfa/parser/cxfa_type.cpp",
       "xfa/fxfa/parser/cxfa_type.h",
       "xfa/fxfa/parser/cxfa_typeface.cpp",
diff --git a/fxjs/CJX_Define.h b/fxjs/CJX_Define.h
new file mode 100644
index 0000000..3d8a84b
--- /dev/null
+++ b/fxjs/CJX_Define.h
@@ -0,0 +1,24 @@
+// 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
+
+#ifndef FXJS_CJX_DEFINE_H_
+#define FXJS_CJX_DEFINE_H_
+
+#include "fxjs/cfxjse_arguments.h"
+
+template <class C, void (C::*M)(CFXJSE_Arguments* args)>
+void JSMethod(C* node, CFXJSE_Arguments* args) {
+  (node->*M)(args);
+}
+
+#define JS_METHOD(method_name, class_name)                                     \
+  static void method_name##_static(CJX_Object* node, CFXJSE_Arguments* args) { \
+    JSMethod<class_name, &class_name::method_name>(                            \
+        static_cast<class_name*>(node), args);                                 \
+  }                                                                            \
+  void method_name(CFXJSE_Arguments* pArguments)
+
+#endif  // FXJS_CJX_DEFINE_H_
diff --git a/fxjs/cfxjse_engine.cpp b/fxjs/cfxjse_engine.cpp
index 821b8da..4f086e2 100644
--- a/fxjs/cfxjse_engine.cpp
+++ b/fxjs/cfxjse_engine.cpp
@@ -23,9 +23,9 @@
 #include "xfa/fxfa/parser/cxfa_localemgr.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/cxfa_nodehelper.h"
-#include "xfa/fxfa/parser/cxfa_nodelist.h"
 #include "xfa/fxfa/parser/cxfa_object.h"
 #include "xfa/fxfa/parser/cxfa_thisproxy.h"
+#include "xfa/fxfa/parser/cxfa_treelist.h"
 #include "xfa/fxfa/parser/xfa_basic_data.h"
 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
@@ -68,38 +68,6 @@
   return static_cast<CXFA_ThisProxy*>(pValue->ToHostObject(pClass));
 }
 
-const XFA_METHODINFO* GetMethodByName(XFA_Element eElement,
-                                      const WideStringView& wsMethodName) {
-  if (wsMethodName.IsEmpty())
-    return nullptr;
-
-  int32_t iElementIndex = static_cast<int32_t>(eElement);
-  while (iElementIndex >= 0 && iElementIndex < g_iScriptIndexCount) {
-    const XFA_SCRIPTHIERARCHY* scriptIndex = g_XFAScriptIndex + iElementIndex;
-    int32_t icount = scriptIndex->wMethodCount;
-    if (icount == 0) {
-      iElementIndex = scriptIndex->wParentIndex;
-      continue;
-    }
-    uint32_t uHash = FX_HashCode_GetW(wsMethodName, false);
-    int32_t iStart = scriptIndex->wMethodStart;
-    // TODO(dsinclair): Switch to std::lower_bound.
-    int32_t iEnd = iStart + icount - 1;
-    do {
-      int32_t iMid = (iStart + iEnd) / 2;
-      const XFA_METHODINFO* pInfo = g_SomMethodData + iMid;
-      if (uHash == pInfo->uHash)
-        return pInfo;
-      if (uHash < pInfo->uHash)
-        iEnd = iMid - 1;
-      else
-        iStart = iMid + 1;
-    } while (iStart <= iEnd);
-    iElementIndex = scriptIndex->wParentIndex;
-  }
-  return nullptr;
-}
-
 }  // namespace
 
 // static.
@@ -289,9 +257,8 @@
 
   CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext();
   pObject = lpScriptContext->GetVariablesThis(pObject);
-  XFA_Element eType = pObject->GetElementType();
   WideString wsPropName = WideString::FromUTF8(szPropName);
-  if (GetMethodByName(eType, wsPropName.AsStringView()))
+  if (pObject->JSObject()->HasMethod(wsPropName))
     return FXJSE_ClassPropType_Method;
 
   return FXJSE_ClassPropType_Property;
@@ -407,7 +374,7 @@
   pObject = lpScriptContext->GetVariablesThis(pObject);
   XFA_Element eType = pObject->GetElementType();
   WideString wsPropName = WideString::FromUTF8(szPropName);
-  if (GetMethodByName(eType, wsPropName.AsStringView()))
+  if (pObject->JSObject()->HasMethod(wsPropName))
     return FXJSE_ClassPropType_Method;
 
   if (bQueryIn &&
@@ -424,17 +391,11 @@
   if (!pObject)
     return;
 
-  CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext();
-  pObject = lpScriptContext->GetVariablesThis(pObject);
-
   WideString wsFunName = WideString::FromUTF8(szFuncName);
-  const XFA_METHODINFO* lpMethodInfo =
-      GetMethodByName(pObject->GetElementType(), wsFunName.AsStringView());
-  if (!lpMethodInfo)
-    return;
+  CFXJSE_Engine* lpScriptContext = pObject->GetDocument()->GetScriptContext();
 
-  CJX_Object* jsObject = pObject->JSObject();
-  (jsObject->*(lpMethodInfo->callback))(&args);
+  pObject = lpScriptContext->GetVariablesThis(pObject);
+  pObject->JSObject()->RunMethod(wsFunName, &args);
 }
 
 bool CFXJSE_Engine::IsStrictScopeInJavaScript() {
@@ -728,7 +689,7 @@
   return nNodes > 0;
 }
 
-void CFXJSE_Engine::AddToCacheList(std::unique_ptr<CXFA_NodeList> pList) {
+void CFXJSE_Engine::AddToCacheList(std::unique_ptr<CXFA_List> pList) {
   m_CacheList.push_back(std::move(pList));
 }
 
diff --git a/fxjs/cfxjse_engine.h b/fxjs/cfxjse_engine.h
index a675a39..5310a5c 100644
--- a/fxjs/cfxjse_engine.h
+++ b/fxjs/cfxjse_engine.h
@@ -19,6 +19,7 @@
 
 #define XFA_RESOLVENODE_TagName 0x0002
 
+class CXFA_List;
 class CFXJSE_ResolveProcessor;
 
 class CFXJSE_Engine {
@@ -62,7 +63,7 @@
                       uint32_t dwStyles,
                       CXFA_Node* bindNode);
   CFXJSE_Value* GetJSValueFromMap(CXFA_Object* pObject);
-  void AddToCacheList(std::unique_ptr<CXFA_NodeList> pList);
+  void AddToCacheList(std::unique_ptr<CXFA_List> pList);
   CXFA_Object* GetThisObject() const { return m_pThisObject; }
   v8::Isolate* GetRuntime() const { return m_pIsolate; }
 
@@ -108,8 +109,8 @@
       m_mapVariableToContext;
   CXFA_EventParam m_eventParam;
   std::vector<CXFA_Node*> m_upObjectArray;
-  // CacheList holds the NodeList items so we can clean them up when we're done.
-  std::vector<std::unique_ptr<CXFA_NodeList>> m_CacheList;
+  // CacheList holds the List items so we can clean them up when we're done.
+  std::vector<std::unique_ptr<CXFA_List>> m_CacheList;
   std::vector<CXFA_Node*>* m_pScriptNodeArray;
   std::unique_ptr<CFXJSE_ResolveProcessor> m_ResolveProcessor;
   std::unique_ptr<CFXJSE_FormCalcContext> m_FM2JSContext;
diff --git a/fxjs/cjx_datawindow.cpp b/fxjs/cjx_datawindow.cpp
index acefb40..0d712ba 100644
--- a/fxjs/cjx_datawindow.cpp
+++ b/fxjs/cjx_datawindow.cpp
@@ -10,18 +10,27 @@
 #include "fxjs/cfxjse_value.h"
 #include "xfa/fxfa/parser/cscript_datawindow.h"
 
+const CJX_MethodSpec CJX_DataWindow::MethodSpecs[] = {
+    {"gotoRecord", gotoRecord_static},
+    {"isRecordGroup", isRecordGroup_static},
+    {"moveCurrentRecord", moveCurrentRecord_static},
+    {"record", record_static},
+    {"", nullptr}};
+
 CJX_DataWindow::CJX_DataWindow(CScript_DataWindow* window)
-    : CJX_Object(window) {}
+    : CJX_Object(window) {
+  DefineMethods(MethodSpecs);
+}
 
 CJX_DataWindow::~CJX_DataWindow() {}
 
-void CJX_DataWindow::MoveCurrentRecord(CFXJSE_Arguments* pArguments) {}
+void CJX_DataWindow::moveCurrentRecord(CFXJSE_Arguments* pArguments) {}
 
-void CJX_DataWindow::Record(CFXJSE_Arguments* pArguments) {}
+void CJX_DataWindow::record(CFXJSE_Arguments* pArguments) {}
 
-void CJX_DataWindow::GotoRecord(CFXJSE_Arguments* pArguments) {}
+void CJX_DataWindow::gotoRecord(CFXJSE_Arguments* pArguments) {}
 
-void CJX_DataWindow::IsRecordGroup(CFXJSE_Arguments* pArguments) {}
+void CJX_DataWindow::isRecordGroup(CFXJSE_Arguments* pArguments) {}
 
 void CJX_DataWindow::RecordsBefore(CFXJSE_Value* pValue,
                                    bool bSetting,
diff --git a/fxjs/cjx_datawindow.h b/fxjs/cjx_datawindow.h
index ccdfea4..e7c39ed 100644
--- a/fxjs/cjx_datawindow.h
+++ b/fxjs/cjx_datawindow.h
@@ -7,10 +7,10 @@
 #ifndef FXJS_CJX_DATAWINDOW_H_
 #define FXJS_CJX_DATAWINDOW_H_
 
+#include "fxjs/CJX_Define.h"
 #include "fxjs/cjx_object.h"
 #include "xfa/fxfa/fxfa_basic.h"
 
-class CFXJSE_Arguments;
 class CFXJSE_Value;
 class CScript_DataWindow;
 
@@ -19,10 +19,6 @@
   explicit CJX_DataWindow(CScript_DataWindow* window);
   ~CJX_DataWindow() override;
 
-  void MoveCurrentRecord(CFXJSE_Arguments* pArguments);
-  void Record(CFXJSE_Arguments* pArguments);
-  void GotoRecord(CFXJSE_Arguments* pArguments);
-  void IsRecordGroup(CFXJSE_Arguments* pArguments);
   void RecordsBefore(CFXJSE_Value* pValue,
                      bool bSetting,
                      XFA_Attribute eAttribute);
@@ -33,6 +29,14 @@
                     bool bSetting,
                     XFA_Attribute eAttribute);
   void IsDefined(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
+
+  JS_METHOD(gotoRecord, CJX_DataWindow);
+  JS_METHOD(isRecordGroup, CJX_DataWindow);
+  JS_METHOD(moveCurrentRecord, CJX_DataWindow);
+  JS_METHOD(record, CJX_DataWindow);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
 };
 
 #endif  // FXJS_CJX_DATAWINDOW_H_
diff --git a/fxjs/cjx_eventpseudomodel.cpp b/fxjs/cjx_eventpseudomodel.cpp
index edadb5d..f78890b 100644
--- a/fxjs/cjx_eventpseudomodel.cpp
+++ b/fxjs/cjx_eventpseudomodel.cpp
@@ -42,8 +42,15 @@
 
 }  // namespace
 
+const CJX_MethodSpec CJX_EventPseudoModel::MethodSpecs[] = {
+    {"emit", emit_static},
+    {"reset", reset_static},
+    {"", nullptr}};
+
 CJX_EventPseudoModel::CJX_EventPseudoModel(CScript_EventPseudoModel* model)
-    : CJX_Object(model) {}
+    : CJX_Object(model) {
+  DefineMethods(MethodSpecs);
+}
 
 CJX_EventPseudoModel::~CJX_EventPseudoModel() {}
 
@@ -143,7 +150,7 @@
   Property(pValue, XFA_Event::Target, bSetting);
 }
 
-void CJX_EventPseudoModel::Emit(CFXJSE_Arguments* pArguments) {
+void CJX_EventPseudoModel::emit(CFXJSE_Arguments* pArguments) {
   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
   if (!pScriptContext)
     return;
@@ -163,7 +170,7 @@
   pWidgetHandler->ProcessEvent(pEventParam->m_pTarget, pEventParam);
 }
 
-void CJX_EventPseudoModel::Reset(CFXJSE_Arguments* pArguments) {
+void CJX_EventPseudoModel::reset(CFXJSE_Arguments* pArguments) {
   CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
   if (!pScriptContext)
     return;
diff --git a/fxjs/cjx_eventpseudomodel.h b/fxjs/cjx_eventpseudomodel.h
index 319bb5d..08cca73 100644
--- a/fxjs/cjx_eventpseudomodel.h
+++ b/fxjs/cjx_eventpseudomodel.h
@@ -7,9 +7,9 @@
 #ifndef FXJS_CJX_EVENTPSEUDOMODEL_H_
 #define FXJS_CJX_EVENTPSEUDOMODEL_H_
 
+#include "fxjs/CJX_Define.h"
 #include "fxjs/cjx_object.h"
 
-class CFXJSE_Arguments;
 class CFXJSE_Value;
 class CScript_EventPseudoModel;
 
@@ -63,11 +63,13 @@
                        XFA_Attribute eAttribute);
   void Target(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
 
-  void Emit(CFXJSE_Arguments* pArguments);
-  void Reset(CFXJSE_Arguments* pArguments);
+  JS_METHOD(emit, CJX_EventPseudoModel);
+  JS_METHOD(reset, CJX_EventPseudoModel);
 
  private:
   void Property(CFXJSE_Value* pValue, XFA_Event dwFlag, bool bSetting);
+
+  static const CJX_MethodSpec MethodSpecs[];
 };
 
 #endif  // FXJS_CJX_EVENTPSEUDOMODEL_H_
diff --git a/fxjs/cjx_hostpseudomodel.cpp b/fxjs/cjx_hostpseudomodel.cpp
index 8838c89..6e0f2f8 100644
--- a/fxjs/cjx_hostpseudomodel.cpp
+++ b/fxjs/cjx_hostpseudomodel.cpp
@@ -49,8 +49,28 @@
 
 }  // namespace
 
+const CJX_MethodSpec CJX_HostPseudoModel::MethodSpecs[] = {
+    {"beep", beep_static},
+    {"documentCountInBatch", documentCountInBatch_static},
+    {"documentInBatch", documentInBatch_static},
+    {"exportData", exportData_static},
+    {"getFocus", getFocus_static},
+    {"gotoURL", gotoURL_static},
+    {"importData", importData_static},
+    {"messageBox", messageBox_static},
+    {"openList", openList_static},
+    {"pageDown", pageDown_static},
+    {"pageUp", pageUp_static},
+    {"print", print_static},
+    {"resetData", resetData_static},
+    {"response", response_static},
+    {"setFocus", setFocus_static},
+    {"", nullptr}};
+
 CJX_HostPseudoModel::CJX_HostPseudoModel(CScript_HostPseudoModel* model)
-    : CJX_Object(model) {}
+    : CJX_Object(model) {
+  DefineMethods(MethodSpecs);
+}
 
 CJX_HostPseudoModel::~CJX_HostPseudoModel() {}
 
@@ -229,7 +249,7 @@
       pNotify->GetAppProvider()->GetAppName().UTF8Encode().AsStringView());
 }
 
-void CJX_HostPseudoModel::GotoURL(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::gotoURL(CFXJSE_Arguments* pArguments) {
   if (!GetDocument()->GetScriptContext()->IsRunAtClient())
     return;
 
@@ -252,7 +272,7 @@
   pNotify->GetDocEnvironment()->GotoURL(hDoc, wsURL);
 }
 
-void CJX_HostPseudoModel::OpenList(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::openList(CFXJSE_Arguments* pArguments) {
   if (!GetDocument()->GetScriptContext()->IsRunAtClient())
     return;
 
@@ -306,7 +326,7 @@
   pNotify->OpenDropDownList(hWidget);
 }
 
-void CJX_HostPseudoModel::Response(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::response(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 4) {
     ThrowParamCountMismatchException(L"response");
@@ -344,12 +364,12 @@
     pValue->SetString(wsAnswer.UTF8Encode().AsStringView());
 }
 
-void CJX_HostPseudoModel::DocumentInBatch(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::documentInBatch(CFXJSE_Arguments* pArguments) {
   if (CFXJSE_Value* pValue = pArguments->GetReturnValue())
     pValue->SetInteger(0);
 }
 
-void CJX_HostPseudoModel::ResetData(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::resetData(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 0 || iLength > 1) {
     ThrowParamCountMismatchException(L"resetData");
@@ -399,7 +419,7 @@
     pNotify->ResetData();
 }
 
-void CJX_HostPseudoModel::Beep(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::beep(CFXJSE_Arguments* pArguments) {
   if (!GetDocument()->GetScriptContext()->IsRunAtClient())
     return;
 
@@ -420,7 +440,7 @@
   pNotify->GetAppProvider()->Beep(dwType);
 }
 
-void CJX_HostPseudoModel::SetFocus(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::setFocus(CFXJSE_Arguments* pArguments) {
   if (!GetDocument()->GetScriptContext()->IsRunAtClient())
     return;
 
@@ -463,7 +483,7 @@
   pNotify->SetFocusWidgetNode(pNode);
 }
 
-void CJX_HostPseudoModel::GetFocus(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::getFocus(CFXJSE_Arguments* pArguments) {
   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
   if (!pNotify)
     return;
@@ -476,7 +496,7 @@
       GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode));
 }
 
-void CJX_HostPseudoModel::MessageBox(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::messageBox(CFXJSE_Arguments* pArguments) {
   if (!GetDocument()->GetScriptContext()->IsRunAtClient())
     return;
 
@@ -541,12 +561,12 @@
   return true;
 }
 
-void CJX_HostPseudoModel::DocumentCountInBatch(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::documentCountInBatch(CFXJSE_Arguments* pArguments) {
   if (CFXJSE_Value* pValue = pArguments->GetReturnValue())
     pValue->SetInteger(0);
 }
 
-void CJX_HostPseudoModel::Print(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::print(CFXJSE_Arguments* pArguments) {
   if (!GetDocument()->GetScriptContext()->IsRunAtClient())
     return;
 
@@ -611,7 +631,7 @@
   pNotify->GetDocEnvironment()->Print(hDoc, nStartPage, nEndPage, dwOptions);
 }
 
-void CJX_HostPseudoModel::ImportData(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::importData(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 0 || iLength > 1) {
     ThrowParamCountMismatchException(L"importData");
@@ -620,7 +640,7 @@
   // Not implemented.
 }
 
-void CJX_HostPseudoModel::ExportData(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::exportData(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 0 || iLength > 2) {
     ThrowParamCountMismatchException(L"exportData");
@@ -644,7 +664,7 @@
   pNotify->GetDocEnvironment()->ExportData(hDoc, wsFilePath, bXDP);
 }
 
-void CJX_HostPseudoModel::PageUp(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::pageUp(CFXJSE_Arguments* pArguments) {
   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
   if (!pNotify)
     return;
@@ -659,7 +679,7 @@
   pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage);
 }
 
-void CJX_HostPseudoModel::PageDown(CFXJSE_Arguments* pArguments) {
+void CJX_HostPseudoModel::pageDown(CFXJSE_Arguments* pArguments) {
   CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
   if (!pNotify)
     return;
@@ -678,14 +698,3 @@
 
   pNotify->GetDocEnvironment()->SetCurrentPage(hDoc, nNewPage);
 }
-
-void CJX_HostPseudoModel::CurrentDateTime(CFXJSE_Arguments* pArguments) {
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  WideString wsDataTime = pNotify->GetCurrentDateTime();
-  CFXJSE_Value* pValue = pArguments->GetReturnValue();
-  if (pValue)
-    pValue->SetString(wsDataTime.UTF8Encode().AsStringView());
-}
diff --git a/fxjs/cjx_hostpseudomodel.h b/fxjs/cjx_hostpseudomodel.h
index 9a71bc4..d5c90aa 100644
--- a/fxjs/cjx_hostpseudomodel.h
+++ b/fxjs/cjx_hostpseudomodel.h
@@ -7,10 +7,10 @@
 #ifndef FXJS_CJX_HOSTPSEUDOMODEL_H_
 #define FXJS_CJX_HOSTPSEUDOMODEL_H_
 
+#include "fxjs/CJX_Define.h"
 #include "fxjs/cjx_object.h"
 #include "xfa/fxfa/fxfa_basic.h"
 
-class CFXJSE_Arguments;
 class CFXJSE_Value;
 class CScript_HostPseudoModel;
 
@@ -36,27 +36,29 @@
   void Variation(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
   void Version(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
   void Name(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
-  void GotoURL(CFXJSE_Arguments* pArguments);
-  void OpenList(CFXJSE_Arguments* pArguments);
-  void Response(CFXJSE_Arguments* pArguments);
-  void DocumentInBatch(CFXJSE_Arguments* pArguments);
-  void ResetData(CFXJSE_Arguments* pArguments);
-  void Beep(CFXJSE_Arguments* pArguments);
-  void SetFocus(CFXJSE_Arguments* pArguments);
-  void GetFocus(CFXJSE_Arguments* pArguments);
-  void MessageBox(CFXJSE_Arguments* pArguments);
-  void DocumentCountInBatch(CFXJSE_Arguments* pArguments);
-  void Print(CFXJSE_Arguments* pArguments);
-  void ImportData(CFXJSE_Arguments* pArguments);
-  void ExportData(CFXJSE_Arguments* pArguments);
-  void PageUp(CFXJSE_Arguments* pArguments);
-  void PageDown(CFXJSE_Arguments* pArguments);
-  void CurrentDateTime(CFXJSE_Arguments* pArguments);
+
+  JS_METHOD(beep, CJX_HostPseudoModel);
+  JS_METHOD(documentCountInBatch, CJX_HostPseudoModel);
+  JS_METHOD(documentInBatch, CJX_HostPseudoModel);
+  JS_METHOD(exportData, CJX_HostPseudoModel);
+  JS_METHOD(getFocus, CJX_HostPseudoModel);
+  JS_METHOD(gotoURL, CJX_HostPseudoModel);
+  JS_METHOD(importData, CJX_HostPseudoModel);
+  JS_METHOD(messageBox, CJX_HostPseudoModel);
+  JS_METHOD(openList, CJX_HostPseudoModel);
+  JS_METHOD(pageDown, CJX_HostPseudoModel);
+  JS_METHOD(pageUp, CJX_HostPseudoModel);
+  JS_METHOD(print, CJX_HostPseudoModel);
+  JS_METHOD(resetData, CJX_HostPseudoModel);
+  JS_METHOD(response, CJX_HostPseudoModel);
+  JS_METHOD(setFocus, CJX_HostPseudoModel);
 
  private:
   bool ValidateArgsForMsg(CFXJSE_Arguments* pArguments,
                           int32_t iArgIndex,
                           WideString& wsValue);
+
+  static const CJX_MethodSpec MethodSpecs[];
 };
 
 #endif  // FXJS_CJX_HOSTPSEUDOMODEL_H_
diff --git a/fxjs/cjx_layoutpseudomodel.cpp b/fxjs/cjx_layoutpseudomodel.cpp
index 9767c15..cc7c154 100644
--- a/fxjs/cjx_layoutpseudomodel.cpp
+++ b/fxjs/cjx_layoutpseudomodel.cpp
@@ -24,8 +24,32 @@
 #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
 #include "xfa/fxfa/parser/cxfa_traversestrategy_contentlayoutitem.h"
 
+const CJX_MethodSpec CJX_LayoutPseudoModel::MethodSpecs[] = {
+    {"absPage", absPage_static},
+    {"absPageCount", absPageCount_static},
+    {"absPageCountInBatch", absPageCountInBatch_static},
+    {"absPageInBatch", absPageInBatch_static},
+    {"absPageSpan", absPageSpan_static},
+    {"h", h_static},
+    {"page", page_static},
+    {"pageContent", pageContent_static},
+    {"pageCount", pageCount_static},
+    {"pageSpan", pageSpan_static},
+    {"relayout", relayout_static},
+    {"relayoutPageArea", relayoutPageArea_static},
+    {"sheet", sheet_static},
+    {"sheetCount", sheetCount_static},
+    {"sheetCountInBatch", sheetCountInBatch_static},
+    {"sheetInBatch", sheetInBatch_static},
+    {"w", w_static},
+    {"x", x_static},
+    {"y", y_static},
+    {"", nullptr}};
+
 CJX_LayoutPseudoModel::CJX_LayoutPseudoModel(CScript_LayoutPseudoModel* model)
-    : CJX_Object(model) {}
+    : CJX_Object(model) {
+  DefineMethods(MethodSpecs);
+}
 
 CJX_LayoutPseudoModel::~CJX_LayoutPseudoModel() {}
 
@@ -122,19 +146,19 @@
   pValue->SetFloat(fValue);
 }
 
-void CJX_LayoutPseudoModel::H(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::h(CFXJSE_Arguments* pArguments) {
   HWXY(pArguments, XFA_LAYOUTMODEL_H);
 }
 
-void CJX_LayoutPseudoModel::W(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::w(CFXJSE_Arguments* pArguments) {
   HWXY(pArguments, XFA_LAYOUTMODEL_W);
 }
 
-void CJX_LayoutPseudoModel::X(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::x(CFXJSE_Arguments* pArguments) {
   HWXY(pArguments, XFA_LAYOUTMODEL_X);
 }
 
-void CJX_LayoutPseudoModel::Y(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::y(CFXJSE_Arguments* pArguments) {
   HWXY(pArguments, XFA_LAYOUTMODEL_Y);
 }
 
@@ -163,11 +187,11 @@
   pArguments->GetReturnValue()->SetInteger(iPageCount);
 }
 
-void CJX_LayoutPseudoModel::PageCount(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::pageCount(CFXJSE_Arguments* pArguments) {
   NumberedPageCount(pArguments, true);
 }
 
-void CJX_LayoutPseudoModel::PageSpan(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::pageSpan(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength != 1) {
     ThrowParamCountMismatchException(L"pageSpan");
@@ -197,7 +221,7 @@
   pValue->SetInteger(iPageSpan);
 }
 
-void CJX_LayoutPseudoModel::Page(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::page(CFXJSE_Arguments* pArguments) {
   PageInternals(pArguments, false);
 }
 
@@ -335,7 +359,7 @@
   return retArray;
 }
 
-void CJX_LayoutPseudoModel::PageContent(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::pageContent(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 3) {
     ThrowParamCountMismatchException(L"pageContent");
@@ -371,19 +395,19 @@
       GetDocument()->GetScriptContext()->GetJseNormalClass());
 }
 
-void CJX_LayoutPseudoModel::AbsPageCount(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::absPageCount(CFXJSE_Arguments* pArguments) {
   NumberedPageCount(pArguments, false);
 }
 
-void CJX_LayoutPseudoModel::AbsPageCountInBatch(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::absPageCountInBatch(CFXJSE_Arguments* pArguments) {
   pArguments->GetReturnValue()->SetInteger(0);
 }
 
-void CJX_LayoutPseudoModel::SheetCountInBatch(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::sheetCountInBatch(CFXJSE_Arguments* pArguments) {
   pArguments->GetReturnValue()->SetInteger(0);
 }
 
-void CJX_LayoutPseudoModel::Relayout(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::relayout(CFXJSE_Arguments* pArguments) {
   CXFA_Node* pRootNode = GetDocument()->GetRoot();
   CXFA_Node* pFormRoot = pRootNode->GetFirstChildByClass(XFA_Element::Form);
   CXFA_Node* pContentRootNode = pFormRoot->GetNodeItem(XFA_NODEITEM_FirstChild);
@@ -394,11 +418,11 @@
   pLayoutProcessor->SetForceReLayout(true);
 }
 
-void CJX_LayoutPseudoModel::AbsPageSpan(CFXJSE_Arguments* pArguments) {
-  PageSpan(pArguments);
+void CJX_LayoutPseudoModel::absPageSpan(CFXJSE_Arguments* pArguments) {
+  pageSpan(pArguments);
 }
 
-void CJX_LayoutPseudoModel::AbsPageInBatch(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::absPageInBatch(CFXJSE_Arguments* pArguments) {
   if (pArguments->GetLength() != 1) {
     ThrowParamCountMismatchException(L"absPageInBatch");
     return;
@@ -407,7 +431,7 @@
   pArguments->GetReturnValue()->SetInteger(0);
 }
 
-void CJX_LayoutPseudoModel::SheetInBatch(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::sheetInBatch(CFXJSE_Arguments* pArguments) {
   if (pArguments->GetLength() != 1) {
     ThrowParamCountMismatchException(L"sheetInBatch");
     return;
@@ -416,17 +440,17 @@
   pArguments->GetReturnValue()->SetInteger(0);
 }
 
-void CJX_LayoutPseudoModel::Sheet(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::sheet(CFXJSE_Arguments* pArguments) {
   PageInternals(pArguments, true);
 }
 
-void CJX_LayoutPseudoModel::RelayoutPageArea(CFXJSE_Arguments* pArguments) {}
+void CJX_LayoutPseudoModel::relayoutPageArea(CFXJSE_Arguments* pArguments) {}
 
-void CJX_LayoutPseudoModel::SheetCount(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::sheetCount(CFXJSE_Arguments* pArguments) {
   NumberedPageCount(pArguments, false);
 }
 
-void CJX_LayoutPseudoModel::AbsPage(CFXJSE_Arguments* pArguments) {
+void CJX_LayoutPseudoModel::absPage(CFXJSE_Arguments* pArguments) {
   PageInternals(pArguments, true);
 }
 
diff --git a/fxjs/cjx_layoutpseudomodel.h b/fxjs/cjx_layoutpseudomodel.h
index 66adb79..9eba2ac 100644
--- a/fxjs/cjx_layoutpseudomodel.h
+++ b/fxjs/cjx_layoutpseudomodel.h
@@ -9,6 +9,7 @@
 
 #include <vector>
 
+#include "fxjs/CJX_Define.h"
 #include "fxjs/cjx_object.h"
 
 enum XFA_LAYOUTMODEL_HWXY {
@@ -31,25 +32,25 @@
 
   void Ready(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
 
-  void H(CFXJSE_Arguments* pArguments);
-  void W(CFXJSE_Arguments* pArguments);
-  void X(CFXJSE_Arguments* pArguments);
-  void Y(CFXJSE_Arguments* pArguments);
-  void PageCount(CFXJSE_Arguments* pArguments);
-  void PageSpan(CFXJSE_Arguments* pArguments);
-  void Page(CFXJSE_Arguments* pArguments);
-  void PageContent(CFXJSE_Arguments* pArguments);
-  void AbsPageCount(CFXJSE_Arguments* pArguments);
-  void AbsPageCountInBatch(CFXJSE_Arguments* pArguments);
-  void SheetCountInBatch(CFXJSE_Arguments* pArguments);
-  void Relayout(CFXJSE_Arguments* pArguments);
-  void AbsPageSpan(CFXJSE_Arguments* pArguments);
-  void AbsPageInBatch(CFXJSE_Arguments* pArguments);
-  void SheetInBatch(CFXJSE_Arguments* pArguments);
-  void Sheet(CFXJSE_Arguments* pArguments);
-  void RelayoutPageArea(CFXJSE_Arguments* pArguments);
-  void SheetCount(CFXJSE_Arguments* pArguments);
-  void AbsPage(CFXJSE_Arguments* pArguments);
+  JS_METHOD(absPage, CJX_LayoutPseudoModel);
+  JS_METHOD(absPageCount, CJX_LayoutPseudoModel);
+  JS_METHOD(absPageCountInBatch, CJX_LayoutPseudoModel);
+  JS_METHOD(absPageInBatch, CJX_LayoutPseudoModel);
+  JS_METHOD(absPageSpan, CJX_LayoutPseudoModel);
+  JS_METHOD(h, CJX_LayoutPseudoModel);
+  JS_METHOD(page, CJX_LayoutPseudoModel);
+  JS_METHOD(pageContent, CJX_LayoutPseudoModel);
+  JS_METHOD(pageCount, CJX_LayoutPseudoModel);
+  JS_METHOD(pageSpan, CJX_LayoutPseudoModel);
+  JS_METHOD(relayout, CJX_LayoutPseudoModel);
+  JS_METHOD(relayoutPageArea, CJX_LayoutPseudoModel);
+  JS_METHOD(sheet, CJX_LayoutPseudoModel);
+  JS_METHOD(sheetCount, CJX_LayoutPseudoModel);
+  JS_METHOD(sheetCountInBatch, CJX_LayoutPseudoModel);
+  JS_METHOD(sheetInBatch, CJX_LayoutPseudoModel);
+  JS_METHOD(w, CJX_LayoutPseudoModel);
+  JS_METHOD(x, CJX_LayoutPseudoModel);
+  JS_METHOD(y, CJX_LayoutPseudoModel);
 
  private:
   void NumberedPageCount(CFXJSE_Arguments* pArguments, bool bNumbered);
@@ -59,6 +60,8 @@
                                       const WideString& wsType,
                                       bool bOnPageArea);
   void PageInternals(CFXJSE_Arguments* pArguments, bool bAbsPage);
+
+  static const CJX_MethodSpec MethodSpecs[];
 };
 
 #endif  // FXJS_CJX_LAYOUTPSEUDOMODEL_H_
diff --git a/fxjs/cjx_logpseudomodel.cpp b/fxjs/cjx_logpseudomodel.cpp
index 815f1a8..7598172 100644
--- a/fxjs/cjx_logpseudomodel.cpp
+++ b/fxjs/cjx_logpseudomodel.cpp
@@ -10,17 +10,27 @@
 #include "fxjs/cfxjse_value.h"
 #include "xfa/fxfa/parser/cscript_logpseudomodel.h"
 
+const CJX_MethodSpec CJX_LogPseudoModel::MethodSpecs[] = {
+    {"message", message_static},
+    {"traceEnabled", traceEnabled_static},
+    {"traceActivate", traceActivate_static},
+    {"traceDeactivate", traceDeactivate_static},
+    {"trace", trace_static},
+    {"", nullptr}};
+
 CJX_LogPseudoModel::CJX_LogPseudoModel(CScript_LogPseudoModel* model)
-    : CJX_Object(model) {}
+    : CJX_Object(model) {
+  DefineMethods(MethodSpecs);
+}
 
 CJX_LogPseudoModel::~CJX_LogPseudoModel() {}
 
-void CJX_LogPseudoModel::Message(CFXJSE_Arguments* pArguments) {}
+void CJX_LogPseudoModel::message(CFXJSE_Arguments* pArguments) {}
 
-void CJX_LogPseudoModel::TraceEnabled(CFXJSE_Arguments* pArguments) {}
+void CJX_LogPseudoModel::traceEnabled(CFXJSE_Arguments* pArguments) {}
 
-void CJX_LogPseudoModel::TraceActivate(CFXJSE_Arguments* pArguments) {}
+void CJX_LogPseudoModel::traceActivate(CFXJSE_Arguments* pArguments) {}
 
-void CJX_LogPseudoModel::TraceDeactivate(CFXJSE_Arguments* pArguments) {}
+void CJX_LogPseudoModel::traceDeactivate(CFXJSE_Arguments* pArguments) {}
 
-void CJX_LogPseudoModel::Trace(CFXJSE_Arguments* pArguments) {}
+void CJX_LogPseudoModel::trace(CFXJSE_Arguments* pArguments) {}
diff --git a/fxjs/cjx_logpseudomodel.h b/fxjs/cjx_logpseudomodel.h
index 26a4702..e22301e 100644
--- a/fxjs/cjx_logpseudomodel.h
+++ b/fxjs/cjx_logpseudomodel.h
@@ -7,10 +7,9 @@
 #ifndef FXJS_CJX_LOGPSEUDOMODEL_H_
 #define FXJS_CJX_LOGPSEUDOMODEL_H_
 
+#include "fxjs/CJX_Define.h"
 #include "fxjs/cjx_object.h"
 
-class CFXJSE_Arguments;
-class CFXJSE_Value;
 class CScript_LogPseudoModel;
 
 class CJX_LogPseudoModel : public CJX_Object {
@@ -18,11 +17,14 @@
   explicit CJX_LogPseudoModel(CScript_LogPseudoModel* model);
   ~CJX_LogPseudoModel() override;
 
-  void Message(CFXJSE_Arguments* pArguments);
-  void TraceEnabled(CFXJSE_Arguments* pArguments);
-  void TraceActivate(CFXJSE_Arguments* pArguments);
-  void TraceDeactivate(CFXJSE_Arguments* pArguments);
-  void Trace(CFXJSE_Arguments* pArguments);
+  JS_METHOD(message, CJX_LogPseudoModel);
+  JS_METHOD(traceEnabled, CJX_LogPseudoModel);
+  JS_METHOD(traceActivate, CJX_LogPseudoModel);
+  JS_METHOD(traceDeactivate, CJX_LogPseudoModel);
+  JS_METHOD(trace, CJX_LogPseudoModel);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
 };
 
 #endif  // FXJS_CJX_LOGPSEUDOMODEL_H_
diff --git a/fxjs/cjx_node.cpp b/fxjs/cjx_node.cpp
index aaff83e..4a07b31 100644
--- a/fxjs/cjx_node.cpp
+++ b/fxjs/cjx_node.cpp
@@ -32,19 +32,6 @@
 
 namespace {
 
-void XFA_DeleteWideString(void* pData) {
-  delete static_cast<WideString*>(pData);
-}
-
-void XFA_CopyWideString(void*& pData) {
-  if (!pData)
-    return;
-  pData = new WideString(*reinterpret_cast<WideString*>(pData));
-}
-
-XFA_MAPDATABLOCKCALLBACKINFO deleteWideStringCallBack = {XFA_DeleteWideString,
-                                                         XFA_CopyWideString};
-
 std::tuple<int32_t, int32_t, int32_t> StrToRGB(const WideString& strRGB) {
   int32_t r = 0;
   int32_t g = 0;
@@ -76,56 +63,45 @@
   return {r, g, b};
 }
 
-enum XFA_KEYTYPE {
-  XFA_KEYTYPE_Custom,
-  XFA_KEYTYPE_Element,
+enum class EventAppliesToo {
+  kNone = 0,
+  kAll = 1,
+  kAllNonRecursive = 2,
+  kSubform = 3,
+  kFieldOrExclusion = 4,
+  kField = 5,
+  kSignature = 6,
+  kChoiceList = 7
 };
 
-void* GetMapKey_Custom(const WideStringView& wsKey) {
-  uint32_t dwKey = FX_HashCode_GetW(wsKey, false);
-  return (void*)(uintptr_t)((dwKey << 1) | XFA_KEYTYPE_Custom);
-}
-
-void* GetMapKey_Element(XFA_Element eType, XFA_Attribute eAttribute) {
-  return (void*)(uintptr_t)((static_cast<uint32_t>(eType) << 16) |
-                            (static_cast<uint32_t>(eAttribute) << 8) |
-                            XFA_KEYTYPE_Element);
-}
-
 struct XFA_ExecEventParaInfo {
  public:
   uint32_t m_uHash;
   const wchar_t* m_lpcEventName;
   XFA_EVENTTYPE m_eventType;
-  uint32_t m_validFlags;
+  EventAppliesToo m_validFlags;
 };
 
 const XFA_ExecEventParaInfo gs_eventParaInfos[] = {
-    {0x02a6c55a, L"postSubmit", XFA_EVENT_PostSubmit, 0},
-    {0x0ab466bb, L"preSubmit", XFA_EVENT_PreSubmit, 0},
-    {0x109d7ce7, L"mouseEnter", XFA_EVENT_MouseEnter, 5},
-    {0x17fad373, L"postPrint", XFA_EVENT_PostPrint, 0},
-    {0x1bfc72d9, L"preOpen", XFA_EVENT_PreOpen, 7},
-    {0x2196a452, L"initialize", XFA_EVENT_Initialize, 1},
-    {0x27410f03, L"mouseExit", XFA_EVENT_MouseExit, 5},
-    {0x33c43dec, L"docClose", XFA_EVENT_DocClose, 0},
-    {0x361fa1b6, L"preSave", XFA_EVENT_PreSave, 0},
-    {0x36f1c6d8, L"preSign", XFA_EVENT_PreSign, 6},
-    {0x4731d6ba, L"exit", XFA_EVENT_Exit, 2},
-    {0x56bf456b, L"docReady", XFA_EVENT_DocReady, 0},
-    {0x7233018a, L"validate", XFA_EVENT_Validate, 1},
-    {0x8808385e, L"indexChange", XFA_EVENT_IndexChange, 3},
-    {0x891f4606, L"change", XFA_EVENT_Change, 4},
-    {0x9528a7b4, L"prePrint", XFA_EVENT_PrePrint, 0},
-    {0x9f693b21, L"mouseDown", XFA_EVENT_MouseDown, 5},
-    {0xcdce56b3, L"full", XFA_EVENT_Full, 4},
-    {0xd576d08e, L"mouseUp", XFA_EVENT_MouseUp, 5},
-    {0xd95657a6, L"click", XFA_EVENT_Click, 4},
-    {0xdbfbe02e, L"calculate", XFA_EVENT_Calculate, 1},
-    {0xe25fa7b8, L"postOpen", XFA_EVENT_PostOpen, 7},
-    {0xe28dce7e, L"enter", XFA_EVENT_Enter, 2},
-    {0xfc82d695, L"postSave", XFA_EVENT_PostSave, 0},
-    {0xfd54fbb7, L"postSign", XFA_EVENT_PostSign, 6},
+    {0x109d7ce7, L"mouseEnter", XFA_EVENT_MouseEnter, EventAppliesToo::kField},
+    {0x1bfc72d9, L"preOpen", XFA_EVENT_PreOpen, EventAppliesToo::kChoiceList},
+    {0x2196a452, L"initialize", XFA_EVENT_Initialize, EventAppliesToo::kAll},
+    {0x27410f03, L"mouseExit", XFA_EVENT_MouseExit, EventAppliesToo::kField},
+    {0x36f1c6d8, L"preSign", XFA_EVENT_PreSign, EventAppliesToo::kSignature},
+    {0x4731d6ba, L"exit", XFA_EVENT_Exit, EventAppliesToo::kAllNonRecursive},
+    {0x7233018a, L"validate", XFA_EVENT_Validate, EventAppliesToo::kAll},
+    {0x8808385e, L"indexChange", XFA_EVENT_IndexChange,
+     EventAppliesToo::kSubform},
+    {0x891f4606, L"change", XFA_EVENT_Change,
+     EventAppliesToo::kFieldOrExclusion},
+    {0x9f693b21, L"mouseDown", XFA_EVENT_MouseDown, EventAppliesToo::kField},
+    {0xcdce56b3, L"full", XFA_EVENT_Full, EventAppliesToo::kFieldOrExclusion},
+    {0xd576d08e, L"mouseUp", XFA_EVENT_MouseUp, EventAppliesToo::kField},
+    {0xd95657a6, L"click", XFA_EVENT_Click, EventAppliesToo::kFieldOrExclusion},
+    {0xdbfbe02e, L"calculate", XFA_EVENT_Calculate, EventAppliesToo::kAll},
+    {0xe25fa7b8, L"postOpen", XFA_EVENT_PostOpen, EventAppliesToo::kChoiceList},
+    {0xe28dce7e, L"enter", XFA_EVENT_Enter, EventAppliesToo::kAllNonRecursive},
+    {0xfd54fbb7, L"postSign", XFA_EVENT_PostSign, EventAppliesToo::kSignature},
 };
 
 const XFA_ExecEventParaInfo* GetEventParaInfoByName(
@@ -148,32 +124,26 @@
 
 }  // namespace
 
-static void XFA_DefaultFreeData(void* pData) {}
+const CJX_MethodSpec CJX_Node::MethodSpecs[] = {
+    {"applyXSL", applyXSL_static},
+    {"assignNode", assignNode_static},
+    {"clone", clone_static},
+    {"getAttribute", getAttribute_static},
+    {"getElement", getElement_static},
+    {"isPropertySpecified", isPropertySpecified_static},
+    {"loadXML", loadXML_static},
+    {"saveFilteredXML", saveFilteredXML_static},
+    {"saveXML", saveXML_static},
+    {"setAttribute", setAttribute_static},
+    {"setElement", setElement_static},
+    {"", nullptr}};
 
-static XFA_MAPDATABLOCKCALLBACKINFO gs_XFADefaultFreeData = {
-    XFA_DefaultFreeData, nullptr};
-
-struct XFA_MAPDATABLOCK {
-  uint8_t* GetData() const { return (uint8_t*)this + sizeof(XFA_MAPDATABLOCK); }
-
-  XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo;
-  int32_t iBytes;
-};
-
-struct XFA_MAPMODULEDATA {
-  XFA_MAPMODULEDATA() {}
-  ~XFA_MAPMODULEDATA() {}
-
-  std::map<void*, void*> m_ValueMap;
-  std::map<void*, XFA_MAPDATABLOCK*> m_BufferMap;
-};
-
-CJX_Node::CJX_Node(CXFA_Node* node) : CJX_Object(node) {}
-
-CJX_Node::~CJX_Node() {
-  ClearMapModuleBuffer();
+CJX_Node::CJX_Node(CXFA_Node* node) : CJX_Tree(node) {
+  DefineMethods(MethodSpecs);
 }
 
+CJX_Node::~CJX_Node() = default;
+
 CXFA_Node* CJX_Node::GetXFANode() {
   return static_cast<CXFA_Node*>(GetXFAObject());
 }
@@ -182,120 +152,6 @@
   return static_cast<const CXFA_Node*>(GetXFAObject());
 }
 
-bool CJX_Node::HasAttribute(XFA_Attribute eAttr) {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  return HasMapModuleKey(pKey);
-}
-
-bool CJX_Node::SetAttribute(XFA_Attribute eAttr,
-                            const WideStringView& wsValue,
-                            bool bNotify) {
-  XFA_AttributeType eType = GetXFANode()->GetAttributeType(eAttr);
-  switch (eType) {
-    case XFA_AttributeType::Enum: {
-      pdfium::Optional<XFA_AttributeEnum> item =
-          CXFA_Node::NameToAttributeEnum(wsValue);
-      return SetEnum(eAttr,
-                     item ? *item : *(GetXFANode()->GetDefaultEnum(eAttr)),
-                     bNotify);
-    }
-    case XFA_AttributeType::CData:
-      return SetCData(eAttr, WideString(wsValue), bNotify, false);
-    case XFA_AttributeType::Boolean:
-      return SetBoolean(eAttr, wsValue != L"0", bNotify);
-    case XFA_AttributeType::Integer:
-      return SetInteger(eAttr,
-                        FXSYS_round(FXSYS_wcstof(wsValue.unterminated_c_str(),
-                                                 wsValue.GetLength(), nullptr)),
-                        bNotify);
-    case XFA_AttributeType::Measure:
-      return SetMeasure(eAttr, CXFA_Measurement(wsValue), bNotify);
-    default:
-      break;
-  }
-  return false;
-}
-
-bool CJX_Node::SetAttribute(const WideStringView& wsAttr,
-                            const WideStringView& wsValue,
-                            bool bNotify) {
-  XFA_Attribute attr = CXFA_Node::NameToAttribute(wsValue);
-  if (attr != XFA_Attribute::Unknown)
-    return SetAttribute(attr, wsValue, bNotify);
-
-  void* pKey = GetMapKey_Custom(wsAttr);
-  SetMapModuleString(pKey, wsValue);
-  return true;
-}
-
-WideString CJX_Node::GetAttribute(const WideStringView& attr) {
-  return TryAttribute(attr, true).value_or(WideString());
-}
-
-WideString CJX_Node::GetAttribute(XFA_Attribute attr) {
-  return TryAttribute(attr, true).value_or(WideString());
-}
-
-pdfium::Optional<WideString> CJX_Node::TryAttribute(XFA_Attribute eAttr,
-                                                    bool bUseDefault) {
-  XFA_AttributeType eType = GetXFANode()->GetAttributeType(eAttr);
-  switch (eType) {
-    case XFA_AttributeType::Enum: {
-      pdfium::Optional<XFA_AttributeEnum> value = TryEnum(eAttr, bUseDefault);
-      if (!value)
-        return {};
-
-      return {CXFA_Node::AttributeEnumToName(*value)};
-    }
-    case XFA_AttributeType::CData:
-      return TryCData(eAttr, bUseDefault);
-
-    case XFA_AttributeType::Boolean: {
-      pdfium::Optional<bool> value = TryBoolean(eAttr, bUseDefault);
-      if (!value)
-        return {};
-      return {*value ? L"1" : L"0"};
-    }
-    case XFA_AttributeType::Integer: {
-      pdfium::Optional<int32_t> iValue = TryInteger(eAttr, bUseDefault);
-      if (!iValue)
-        return {};
-      return {WideString::Format(L"%d", *iValue)};
-    }
-    case XFA_AttributeType::Measure: {
-      pdfium::Optional<CXFA_Measurement> value = TryMeasure(eAttr, bUseDefault);
-      if (!value)
-        return {};
-
-      return {value->ToString()};
-    }
-    default:
-      break;
-  }
-  return {};
-}
-
-pdfium::Optional<WideString> CJX_Node::TryAttribute(
-    const WideStringView& wsAttr,
-    bool bUseDefault) {
-  XFA_Attribute attr = CXFA_Node::NameToAttribute(wsAttr);
-  if (attr != XFA_Attribute::Unknown)
-    return TryAttribute(attr, bUseDefault);
-
-  void* pKey = GetMapKey_Custom(wsAttr);
-  WideStringView wsValueC;
-  if (!GetMapModuleString(pKey, wsValueC))
-    return {};
-
-  return {WideString(wsValueC)};
-}
-
-void CJX_Node::RemoveAttribute(const WideStringView& wsAttr) {
-  void* pKey = GetMapKey_Custom(wsAttr);
-  if (pKey)
-    RemoveMapModuleKey(pKey);
-}
-
 int32_t CJX_Node::Subform_and_SubformSet_InstanceIndex() {
   int32_t index = 0;
   for (CXFA_Node* pNode = GetXFANode()->GetNodeItem(XFA_NODEITEM_PrevSibling);
@@ -393,207 +249,7 @@
   return 0;
 }
 
-void CJX_Node::Script_TreeClass_ResolveNode(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength != 1) {
-    ThrowParamCountMismatchException(L"resolveNode");
-    return;
-  }
-  WideString wsExpression =
-      WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringView());
-  CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
-  if (!pScriptContext)
-    return;
-  CXFA_Node* refNode = GetXFANode();
-  if (refNode->GetElementType() == XFA_Element::Xfa)
-    refNode = ToNode(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(refNode, wsExpression.AsStringView(),
-                                      &resolveNodeRS, dwFlag, nullptr)) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-  if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
-    CXFA_Object* pObject = resolveNodeRS.objects.front();
-    pArguments->GetReturnValue()->Assign(
-        pScriptContext->GetJSValueFromMap(pObject));
-  } else {
-    const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo =
-        resolveNodeRS.pScriptAttribute;
-    if (lpAttributeInfo &&
-        lpAttributeInfo->eValueType == XFA_ScriptType::Object) {
-      auto pValue =
-          pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetRuntime());
-      CJX_Object* jsObject = resolveNodeRS.objects.front()->JSObject();
-      (jsObject->*(lpAttributeInfo->callback))(pValue.get(), false,
-                                               lpAttributeInfo->attribute);
-      pArguments->GetReturnValue()->Assign(pValue.get());
-    } else {
-      pArguments->GetReturnValue()->SetNull();
-    }
-  }
-}
-
-void CJX_Node::Script_TreeClass_ResolveNodes(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength != 1) {
-    ThrowParamCountMismatchException(L"resolveNodes");
-    return;
-  }
-
-  WideString wsExpression =
-      WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringView());
-  CFXJSE_Value* pValue = pArguments->GetReturnValue();
-  if (!pValue)
-    return;
-
-  CXFA_Node* refNode = GetXFANode();
-  if (refNode->GetElementType() == XFA_Element::Xfa)
-    refNode = ToNode(GetDocument()->GetScriptContext()->GetThisObject());
-
-  ResolveNodeList(pValue, wsExpression,
-                  XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
-                      XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
-                      XFA_RESOLVENODE_Siblings,
-                  refNode);
-}
-
-void CJX_Node::ResolveNodeList(CFXJSE_Value* pValue,
-                               WideString wsExpression,
-                               uint32_t dwFlag,
-                               CXFA_Node* refNode) {
-  CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
-  if (!pScriptContext)
-    return;
-  if (!refNode)
-    refNode = GetXFANode();
-
-  XFA_RESOLVENODE_RS resolveNodeRS;
-  pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(),
-                                 &resolveNodeRS, dwFlag, nullptr);
-  CXFA_ArrayNodeList* pNodeList = new CXFA_ArrayNodeList(GetDocument());
-  if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
-    for (CXFA_Object* pObject : resolveNodeRS.objects) {
-      if (pObject->IsNode())
-        pNodeList->Append(pObject->AsNode());
-    }
-  } else {
-    if (resolveNodeRS.pScriptAttribute &&
-        resolveNodeRS.pScriptAttribute->eValueType == XFA_ScriptType::Object) {
-      for (CXFA_Object* pObject : resolveNodeRS.objects) {
-        auto pValue =
-            pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetRuntime());
-        CJX_Object* jsObject = pObject->JSObject();
-        (jsObject->*(resolveNodeRS.pScriptAttribute->callback))(
-            pValue.get(), false, resolveNodeRS.pScriptAttribute->attribute);
-
-        CXFA_Object* obj = CFXJSE_Engine::ToObject(pValue.get(), nullptr);
-        if (obj->IsNode())
-          pNodeList->Append(obj->AsNode());
-      }
-    }
-  }
-  pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
-}
-
-void CJX_Node::Script_TreeClass_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_Node::Script_TreeClass_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(), GetXFANode());
-  pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
-}
-
-void CJX_Node::Script_TreeClass_ClassAll(CFXJSE_Value* pValue,
-                                         bool bSetting,
-                                         XFA_Attribute eAttribute) {
-  if (bSetting) {
-    ThrowInvalidPropertyException();
-    return;
-  }
-
-  WideString wsExpression = L"#" + GetXFANode()->GetClassName() + L"[*]";
-  ResolveNodeList(pValue, wsExpression,
-                  XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL, nullptr);
-}
-
-void CJX_Node::Script_TreeClass_Parent(CFXJSE_Value* pValue,
-                                       bool bSetting,
-                                       XFA_Attribute eAttribute) {
-  if (bSetting) {
-    ThrowInvalidPropertyException();
-    return;
-  }
-
-  CXFA_Node* pParent = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-  if (!pParent) {
-    pValue->SetNull();
-    return;
-  }
-
-  pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pParent));
-}
-
-void CJX_Node::Script_TreeClass_Index(CFXJSE_Value* pValue,
-                                      bool bSetting,
-                                      XFA_Attribute eAttribute) {
-  if (bSetting) {
-    ThrowInvalidPropertyException();
-    return;
-  }
-  pValue->SetInteger(GetXFANode()->GetNodeSameNameIndex());
-}
-
-void CJX_Node::Script_TreeClass_ClassIndex(CFXJSE_Value* pValue,
-                                           bool bSetting,
-                                           XFA_Attribute eAttribute) {
-  if (bSetting) {
-    ThrowInvalidPropertyException();
-    return;
-  }
-  pValue->SetInteger(GetXFANode()->GetNodeSameClassIndex());
-}
-
-void CJX_Node::Script_TreeClass_SomExpression(CFXJSE_Value* pValue,
-                                              bool bSetting,
-                                              XFA_Attribute eAttribute) {
-  if (bSetting) {
-    ThrowInvalidPropertyException();
-    return;
-  }
-
-  WideString wsSOMExpression;
-  GetXFANode()->GetSOMExpression(wsSOMExpression);
-  pValue->SetString(wsSOMExpression.UTF8Encode().AsStringView());
-}
-
-void CJX_Node::Script_NodeClass_ApplyXSL(CFXJSE_Arguments* pArguments) {
+void CJX_Node::applyXSL(CFXJSE_Arguments* pArguments) {
   if (pArguments->GetLength() != 1) {
     ThrowParamCountMismatchException(L"applyXSL");
     return;
@@ -602,7 +258,7 @@
   // TODO(weili): check whether we need to implement this, pdfium:501.
 }
 
-void CJX_Node::Script_NodeClass_AssignNode(CFXJSE_Arguments* pArguments) {
+void CJX_Node::assignNode(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 3) {
     ThrowParamCountMismatchException(L"assignNode");
@@ -612,7 +268,7 @@
   // TODO(weili): check whether we need to implement this, pdfium:501.
 }
 
-void CJX_Node::Script_NodeClass_Clone(CFXJSE_Arguments* pArguments) {
+void CJX_Node::clone(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength != 1) {
     ThrowParamCountMismatchException(L"clone");
@@ -624,7 +280,7 @@
       GetDocument()->GetScriptContext()->GetJSValueFromMap(pCloneNode));
 }
 
-void CJX_Node::Script_NodeClass_GetAttribute(CFXJSE_Arguments* pArguments) {
+void CJX_Node::getAttribute(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength != 1) {
     ThrowParamCountMismatchException(L"getAttribute");
@@ -641,7 +297,7 @@
       GetAttribute(wsExpression.AsStringView()).UTF8Encode().AsStringView());
 }
 
-void CJX_Node::Script_NodeClass_GetElement(CFXJSE_Arguments* pArguments) {
+void CJX_Node::getElement(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 2) {
     ThrowParamCountMismatchException(L"getElement");
@@ -658,8 +314,7 @@
       GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode));
 }
 
-void CJX_Node::Script_NodeClass_IsPropertySpecified(
-    CFXJSE_Arguments* pArguments) {
+void CJX_Node::isPropertySpecified(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 3) {
     ThrowParamCountMismatchException(L"isPropertySpecified");
@@ -691,7 +346,7 @@
   pValue->SetBoolean(bHas);
 }
 
-void CJX_Node::Script_NodeClass_LoadXML(CFXJSE_Arguments* pArguments) {
+void CJX_Node::loadXML(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 3) {
     ThrowParamCountMismatchException(L"loadXML");
@@ -811,11 +466,11 @@
   pFakeRoot->SetFlag(XFA_NodeFlag_HasRemovedChildren, false);
 }
 
-void CJX_Node::Script_NodeClass_SaveFilteredXML(CFXJSE_Arguments* pArguments) {
+void CJX_Node::saveFilteredXML(CFXJSE_Arguments* pArguments) {
   // TODO(weili): Check whether we need to implement this, pdfium:501.
 }
 
-void CJX_Node::Script_NodeClass_SaveXML(CFXJSE_Arguments* pArguments) {
+void CJX_Node::saveXML(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 0 || iLength > 1) {
     ThrowParamCountMismatchException(L"saveXML");
@@ -862,7 +517,7 @@
       ByteStringView(pMemoryStream->GetBuffer(), pMemoryStream->GetSize()));
 }
 
-void CJX_Node::Script_NodeClass_SetAttribute(CFXJSE_Arguments* pArguments) {
+void CJX_Node::setAttribute(CFXJSE_Arguments* pArguments) {
   if (pArguments->GetLength() != 2) {
     ThrowParamCountMismatchException(L"setAttribute");
     return;
@@ -876,7 +531,7 @@
                true);
 }
 
-void CJX_Node::Script_NodeClass_SetElement(CFXJSE_Arguments* pArguments) {
+void CJX_Node::setElement(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength != 1 && iLength != 2) {
     ThrowParamCountMismatchException(L"setElement");
@@ -950,40 +605,6 @@
   }
 }
 
-void CJX_Node::Script_ContainerClass_GetDelta(CFXJSE_Arguments* pArguments) {}
-
-void CJX_Node::Script_ContainerClass_GetDeltas(CFXJSE_Arguments* pArguments) {
-  CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(GetDocument());
-  pArguments->GetReturnValue()->SetObject(
-      pFormNodes, GetDocument()->GetScriptContext()->GetJseNormalClass());
-}
-
-void CJX_Node::Script_ModelClass_ClearErrorList(CFXJSE_Arguments* pArguments) {}
-
-void CJX_Node::Script_ModelClass_CreateNode(CFXJSE_Arguments* pArguments) {
-  Script_Template_CreateNode(pArguments);
-}
-
-void CJX_Node::Script_ModelClass_IsCompatibleNS(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength < 1) {
-    ThrowParamCountMismatchException(L"isCompatibleNS");
-    return;
-  }
-
-  WideString wsNameSpace;
-  if (iLength >= 1) {
-    ByteString bsNameSpace = pArguments->GetUTF8String(0);
-    wsNameSpace = WideString::FromUTF8(bsNameSpace.AsStringView());
-  }
-
-  CFXJSE_Value* pValue = pArguments->GetReturnValue();
-  if (!pValue)
-    return;
-
-  pValue->SetBoolean(TryNamespace().value_or(WideString()) == wsNameSpace);
-}
-
 void CJX_Node::Script_ModelClass_Context(CFXJSE_Value* pValue,
                                          bool bSetting,
                                          XFA_Attribute eAttribute) {}
@@ -1032,182 +653,6 @@
   pValue->SetString(GetBoolean(eAttribute) ? "1" : "0");
 }
 
-void CJX_Node::OnChanging(XFA_Attribute eAttr, bool bNotify) {
-  if (!bNotify || !GetXFANode()->IsInitialized())
-    return;
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (pNotify)
-    pNotify->OnValueChanging(GetXFANode(), eAttr);
-}
-
-void CJX_Node::OnChanged(XFA_Attribute eAttr,
-                         bool bNotify,
-                         bool bScriptModify) {
-  if (bNotify && GetXFANode()->IsInitialized())
-    SendAttributeChangeMessage(eAttr, bScriptModify);
-}
-
-void CJX_Node::SendAttributeChangeMessage(XFA_Attribute eAttribute,
-                                          bool bScriptModify) {
-  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
-  if (!pLayoutPro)
-    return;
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  if (GetXFANode()->GetPacketType() != XFA_PacketType::Form) {
-    pNotify->OnValueChanged(GetXFANode(), eAttribute, GetXFANode(),
-                            GetXFANode());
-    return;
-  }
-
-  bool bNeedFindContainer = false;
-  switch (GetXFANode()->GetElementType()) {
-    case XFA_Element::Caption:
-      bNeedFindContainer = true;
-      pNotify->OnValueChanged(GetXFANode(), eAttribute, GetXFANode(),
-                              GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent));
-      break;
-    case XFA_Element::Font:
-    case XFA_Element::Para: {
-      bNeedFindContainer = true;
-      CXFA_Node* pParentNode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-      if (pParentNode->GetElementType() == XFA_Element::Caption) {
-        pNotify->OnValueChanged(GetXFANode(), eAttribute, pParentNode,
-                                pParentNode->GetNodeItem(XFA_NODEITEM_Parent));
-      } else {
-        pNotify->OnValueChanged(GetXFANode(), eAttribute, GetXFANode(),
-                                pParentNode);
-      }
-      break;
-    }
-    case XFA_Element::Margin: {
-      bNeedFindContainer = true;
-      CXFA_Node* pParentNode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-      XFA_Element eParentType = pParentNode->GetElementType();
-      if (pParentNode->IsContainerNode()) {
-        pNotify->OnValueChanged(GetXFANode(), eAttribute, GetXFANode(),
-                                pParentNode);
-      } else if (eParentType == XFA_Element::Caption) {
-        pNotify->OnValueChanged(GetXFANode(), eAttribute, pParentNode,
-                                pParentNode->GetNodeItem(XFA_NODEITEM_Parent));
-      } else {
-        CXFA_Node* pNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
-        if (pNode && pNode->GetElementType() == XFA_Element::Ui) {
-          pNotify->OnValueChanged(GetXFANode(), eAttribute, pNode,
-                                  pNode->GetNodeItem(XFA_NODEITEM_Parent));
-        }
-      }
-      break;
-    }
-    case XFA_Element::Comb: {
-      CXFA_Node* pEditNode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-      XFA_Element eUIType = pEditNode->GetElementType();
-      if (pEditNode && (eUIType == XFA_Element::DateTimeEdit ||
-                        eUIType == XFA_Element::NumericEdit ||
-                        eUIType == XFA_Element::TextEdit)) {
-        CXFA_Node* pUINode = pEditNode->GetNodeItem(XFA_NODEITEM_Parent);
-        if (pUINode) {
-          pNotify->OnValueChanged(GetXFANode(), eAttribute, pUINode,
-                                  pUINode->GetNodeItem(XFA_NODEITEM_Parent));
-        }
-      }
-      break;
-    }
-    case XFA_Element::Button:
-    case XFA_Element::Barcode:
-    case XFA_Element::ChoiceList:
-    case XFA_Element::DateTimeEdit:
-    case XFA_Element::NumericEdit:
-    case XFA_Element::PasswordEdit:
-    case XFA_Element::TextEdit: {
-      CXFA_Node* pUINode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-      if (pUINode) {
-        pNotify->OnValueChanged(GetXFANode(), eAttribute, pUINode,
-                                pUINode->GetNodeItem(XFA_NODEITEM_Parent));
-      }
-      break;
-    }
-    case XFA_Element::CheckButton: {
-      bNeedFindContainer = true;
-      CXFA_Node* pUINode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-      if (pUINode) {
-        pNotify->OnValueChanged(GetXFANode(), eAttribute, pUINode,
-                                pUINode->GetNodeItem(XFA_NODEITEM_Parent));
-      }
-      break;
-    }
-    case XFA_Element::Keep:
-    case XFA_Element::Bookend:
-    case XFA_Element::Break:
-    case XFA_Element::BreakAfter:
-    case XFA_Element::BreakBefore:
-    case XFA_Element::Overflow:
-      bNeedFindContainer = true;
-      break;
-    case XFA_Element::Area:
-    case XFA_Element::Draw:
-    case XFA_Element::ExclGroup:
-    case XFA_Element::Field:
-    case XFA_Element::Subform:
-    case XFA_Element::SubformSet:
-      pLayoutPro->AddChangedContainer(GetXFANode());
-      pNotify->OnValueChanged(GetXFANode(), eAttribute, GetXFANode(),
-                              GetXFANode());
-      break;
-    case XFA_Element::Sharptext:
-    case XFA_Element::Sharpxml:
-    case XFA_Element::SharpxHTML: {
-      CXFA_Node* pTextNode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-      if (!pTextNode)
-        return;
-
-      CXFA_Node* pValueNode = pTextNode->GetNodeItem(XFA_NODEITEM_Parent);
-      if (!pValueNode)
-        return;
-
-      XFA_Element eType = pValueNode->GetElementType();
-      if (eType == XFA_Element::Value) {
-        bNeedFindContainer = true;
-        CXFA_Node* pNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent);
-        if (pNode && pNode->IsContainerNode()) {
-          if (bScriptModify)
-            pValueNode = pNode;
-
-          pNotify->OnValueChanged(GetXFANode(), eAttribute, pValueNode, pNode);
-        } else {
-          pNotify->OnValueChanged(GetXFANode(), eAttribute, pNode,
-                                  pNode->GetNodeItem(XFA_NODEITEM_Parent));
-        }
-      } else {
-        if (eType == XFA_Element::Items) {
-          CXFA_Node* pNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent);
-          if (pNode && pNode->IsContainerNode()) {
-            pNotify->OnValueChanged(GetXFANode(), eAttribute, pValueNode,
-                                    pNode);
-          }
-        }
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
-  if (!bNeedFindContainer)
-    return;
-
-  CXFA_Node* pParent = GetXFANode();
-  while (pParent && !pParent->IsContainerNode())
-    pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent);
-
-  if (pParent)
-    pLayoutPro->AddChangedContainer(pParent);
-}
-
 void CJX_Node::Script_Attribute_String(CFXJSE_Value* pValue,
                                        bool bSetting,
                                        XFA_Attribute eAttribute) {
@@ -1285,20 +730,6 @@
   pValue->SetString(GetAttribute(eAttribute).UTF8Encode().AsStringView());
 }
 
-void CJX_Node::Script_WsdlConnection_Execute(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 0 && argc != 1) {
-    ThrowParamCountMismatchException(L"execute");
-    return;
-  }
-  pArguments->GetReturnValue()->SetBoolean(false);
-}
-
-void CJX_Node::Script_Delta_Restore(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"restore");
-}
-
 void CJX_Node::Script_Delta_CurrentValue(CFXJSE_Value* pValue,
                                          bool bSetting,
                                          XFA_Attribute eAttribute) {}
@@ -1805,234 +1236,6 @@
   pWidgetData->SetItemState(iIndex, true, true, true, true);
 }
 
-void CJX_Node::Script_Field_ClearItems(CFXJSE_Arguments* pArguments) {
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData)
-    return;
-
-  pWidgetData->DeleteItem(-1, true, false);
-}
-
-void CJX_Node::Script_Field_ExecEvent(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"execEvent");
-    return;
-  }
-
-  ByteString eventString = pArguments->GetUTF8String(0);
-  int32_t iRet = execSingleEventByName(
-      WideString::FromUTF8(eventString.AsStringView()).AsStringView(),
-      XFA_Element::Field);
-  if (eventString != "validate")
-    return;
-
-  pArguments->GetReturnValue()->SetBoolean(
-      (iRet == XFA_EVENTERROR_Error) ? false : true);
-}
-
-void CJX_Node::Script_Field_ExecInitialize(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execInitialize");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize, false,
-                                false);
-}
-
-void CJX_Node::Script_Field_DeleteItem(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength != 1) {
-    ThrowParamCountMismatchException(L"deleteItem");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData)
-    return;
-
-  int32_t iIndex = pArguments->GetInt32(0);
-  bool bValue = pWidgetData->DeleteItem(iIndex, true, true);
-  CFXJSE_Value* pValue = pArguments->GetReturnValue();
-  if (pValue)
-    pValue->SetBoolean(bValue);
-}
-
-void CJX_Node::Script_Field_GetSaveItem(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength != 1) {
-    ThrowParamCountMismatchException(L"getSaveItem");
-    return;
-  }
-
-  int32_t iIndex = pArguments->GetInt32(0);
-  if (iIndex < 0) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-
-  pdfium::Optional<WideString> value =
-      pWidgetData->GetChoiceListItem(iIndex, true);
-  if (!value) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-  pArguments->GetReturnValue()->SetString(value->UTF8Encode().AsStringView());
-}
-
-void CJX_Node::Script_Field_BoundItem(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength != 1) {
-    ThrowParamCountMismatchException(L"boundItem");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData)
-    return;
-
-  ByteString bsValue = pArguments->GetUTF8String(0);
-  WideString wsValue = WideString::FromUTF8(bsValue.AsStringView());
-  WideString wsBoundValue = pWidgetData->GetItemValue(wsValue.AsStringView());
-  CFXJSE_Value* pValue = pArguments->GetReturnValue();
-  if (pValue)
-    pValue->SetString(wsBoundValue.UTF8Encode().AsStringView());
-}
-
-void CJX_Node::Script_Field_GetItemState(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength != 1) {
-    ThrowParamCountMismatchException(L"getItemState");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData)
-    return;
-
-  CFXJSE_Value* pValue = pArguments->GetReturnValue();
-  if (pValue)
-    pValue->SetBoolean(pWidgetData->GetItemState(pArguments->GetInt32(0)));
-}
-
-void CJX_Node::Script_Field_ExecCalculate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execCalculate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate, false,
-                                false);
-}
-
-void CJX_Node::Script_Field_SetItems(CFXJSE_Arguments* pArguments) {}
-
-void CJX_Node::Script_Field_GetDisplayItem(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength != 1) {
-    ThrowParamCountMismatchException(L"getDisplayItem");
-    return;
-  }
-
-  int32_t iIndex = pArguments->GetInt32(0);
-  if (iIndex < 0) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-
-  pdfium::Optional<WideString> value =
-      pWidgetData->GetChoiceListItem(iIndex, false);
-  if (!value) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-  pArguments->GetReturnValue()->SetString(value->UTF8Encode().AsStringView());
-}
-
-void CJX_Node::Script_Field_SetItemState(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 2) {
-    ThrowParamCountMismatchException(L"setItemState");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData)
-    return;
-
-  int32_t iIndex = pArguments->GetInt32(0);
-  if (pArguments->GetInt32(1) != 0) {
-    pWidgetData->SetItemState(iIndex, true, true, true, true);
-    return;
-  }
-
-  if (pWidgetData->GetItemState(iIndex))
-    pWidgetData->SetItemState(iIndex, false, true, true, true);
-}
-
-void CJX_Node::Script_Field_AddItem(CFXJSE_Arguments* pArguments) {
-  int32_t iLength = pArguments->GetLength();
-  if (iLength < 1 || iLength > 2) {
-    ThrowParamCountMismatchException(L"addItem");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData)
-    return;
-
-  WideString wsLabel;
-  if (iLength >= 1) {
-    ByteString bsLabel = pArguments->GetUTF8String(0);
-    wsLabel = WideString::FromUTF8(bsLabel.AsStringView());
-  }
-
-  WideString wsValue;
-  if (iLength >= 2) {
-    ByteString bsValue = pArguments->GetUTF8String(1);
-    wsValue = WideString::FromUTF8(bsValue.AsStringView());
-  }
-
-  pWidgetData->InsertItem(wsLabel, wsValue, true);
-}
-
-void CJX_Node::Script_Field_ExecValidate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execValidate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify) {
-    pArguments->GetReturnValue()->SetBoolean(false);
-    return;
-  }
-
-  int32_t iRet = pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate,
-                                               false, false);
-  pArguments->GetReturnValue()->SetBoolean(
-      (iRet == XFA_EVENTERROR_Error) ? false : true);
-}
-
 void CJX_Node::Script_ExclGroup_ErrorText(CFXJSE_Value* pValue,
                                           bool bSetting,
                                           XFA_Attribute eAttribute) {
@@ -2066,93 +1269,6 @@
                                           bool bSetting,
                                           XFA_Attribute eAttribute) {}
 
-void CJX_Node::Script_ExclGroup_ExecEvent(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"execEvent");
-    return;
-  }
-
-  ByteString eventString = pArguments->GetUTF8String(0);
-  execSingleEventByName(
-      WideString::FromUTF8(eventString.AsStringView()).AsStringView(),
-      XFA_Element::ExclGroup);
-}
-
-void CJX_Node::Script_ExclGroup_SelectedMember(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc < 0 || argc > 1) {
-    ThrowParamCountMismatchException(L"selectedMember");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-
-  CXFA_Node* pReturnNode = nullptr;
-  if (argc == 0) {
-    pReturnNode = pWidgetData->GetSelectedMember();
-  } else {
-    ByteString szName;
-    szName = pArguments->GetUTF8String(0);
-    pReturnNode = pWidgetData->SetSelectedMember(
-        WideString::FromUTF8(szName.AsStringView()).AsStringView(), true);
-  }
-  if (!pReturnNode) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-
-  pArguments->GetReturnValue()->Assign(
-      GetDocument()->GetScriptContext()->GetJSValueFromMap(pReturnNode));
-}
-
-void CJX_Node::Script_ExclGroup_ExecInitialize(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execInitialize");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize);
-}
-
-void CJX_Node::Script_ExclGroup_ExecCalculate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execCalculate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
-}
-
-void CJX_Node::Script_ExclGroup_ExecValidate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execValidate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify) {
-    pArguments->GetReturnValue()->SetBoolean(false);
-    return;
-  }
-
-  int32_t iRet =
-      pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
-  pArguments->GetReturnValue()->SetBoolean(
-      (iRet == XFA_EVENTERROR_Error) ? false : true);
-}
-
 void CJX_Node::Script_Som_InstanceIndex(CFXJSE_Value* pValue,
                                         bool bSetting,
                                         XFA_Attribute eAttribute) {
@@ -2234,188 +1350,6 @@
   pValue->SetString(wsLocaleName.UTF8Encode().AsStringView());
 }
 
-void CJX_Node::Script_Subform_ExecEvent(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"execEvent");
-    return;
-  }
-
-  ByteString eventString = pArguments->GetUTF8String(0);
-  execSingleEventByName(
-      WideString::FromUTF8(eventString.AsStringView()).AsStringView(),
-      XFA_Element::Subform);
-}
-
-void CJX_Node::Script_Subform_ExecInitialize(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execInitialize");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize);
-}
-
-void CJX_Node::Script_Subform_ExecCalculate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execCalculate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
-}
-
-void CJX_Node::Script_Subform_ExecValidate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execValidate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify) {
-    pArguments->GetReturnValue()->SetBoolean(false);
-    return;
-  }
-
-  int32_t iRet =
-      pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
-  pArguments->GetReturnValue()->SetBoolean(
-      (iRet == XFA_EVENTERROR_Error) ? false : true);
-}
-
-void CJX_Node::Script_Subform_GetInvalidObjects(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"getInvalidObjects");
-}
-
-void CJX_Node::Script_Template_FormNodes(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"formNodes");
-    return;
-  }
-  pArguments->GetReturnValue()->SetBoolean(true);
-}
-
-void CJX_Node::Script_Template_Remerge(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"remerge");
-    return;
-  }
-  GetDocument()->DoDataRemerge(true);
-}
-
-void CJX_Node::Script_Template_ExecInitialize(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execInitialize");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData) {
-    pArguments->GetReturnValue()->SetBoolean(false);
-    return;
-  }
-  pArguments->GetReturnValue()->SetBoolean(true);
-}
-
-void CJX_Node::Script_Template_CreateNode(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc <= 0 || argc >= 4) {
-    ThrowParamCountMismatchException(L"createNode");
-    return;
-  }
-
-  WideString strName;
-  WideString strNameSpace;
-  if (argc > 1) {
-    ByteString bsName = pArguments->GetUTF8String(1);
-    strName = WideString::FromUTF8(bsName.AsStringView());
-    if (argc == 3) {
-      ByteString bsNameSpace = pArguments->GetUTF8String(2);
-      strNameSpace = WideString::FromUTF8(bsNameSpace.AsStringView());
-    }
-  }
-
-  ByteString bsTagName = pArguments->GetUTF8String(0);
-  WideString strTagName = WideString::FromUTF8(bsTagName.AsStringView());
-  XFA_Element eType = CXFA_Node::NameToElement(strTagName);
-  CXFA_Node* pNewNode = GetXFANode()->CreateSamePacketNode(eType);
-  if (!pNewNode) {
-    pArguments->GetReturnValue()->SetNull();
-    return;
-  }
-
-  if (strName.IsEmpty()) {
-    pArguments->GetReturnValue()->Assign(
-        GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewNode));
-    return;
-  }
-
-  if (!pNewNode->HasAttribute(XFA_Attribute::Name)) {
-    ThrowMissingPropertyException(strTagName, L"name");
-    return;
-  }
-
-  pNewNode->JSNode()->SetAttribute(XFA_Attribute::Name, strName.AsStringView(),
-                                   true);
-  if (pNewNode->GetPacketType() == XFA_PacketType::Datasets)
-    pNewNode->CreateXMLMappingNode();
-
-  pArguments->GetReturnValue()->Assign(
-      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewNode));
-}
-
-void CJX_Node::Script_Template_Recalculate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"recalculate");
-    return;
-  }
-  pArguments->GetReturnValue()->SetBoolean(true);
-}
-
-void CJX_Node::Script_Template_ExecCalculate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execCalculate");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData) {
-    pArguments->GetReturnValue()->SetBoolean(false);
-    return;
-  }
-  pArguments->GetReturnValue()->SetBoolean(true);
-}
-
-void CJX_Node::Script_Template_ExecValidate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execValidate");
-    return;
-  }
-  pArguments->GetReturnValue()->SetBoolean(!!GetXFANode()->GetWidgetData());
-}
-
-void CJX_Node::Script_Manifest_Evaluate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"evaluate");
-    return;
-  }
-
-  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-  if (!pWidgetData) {
-    pArguments->GetReturnValue()->SetBoolean(false);
-    return;
-  }
-  pArguments->GetReturnValue()->SetBoolean(true);
-}
-
 void CJX_Node::Script_InstanceManager_Max(CFXJSE_Value* pValue,
                                           bool bSetting,
                                           XFA_Attribute eAttribute) {
@@ -2446,160 +1380,6 @@
   InstanceManager_SetInstances(pValue->ToInteger());
 }
 
-void CJX_Node::Script_InstanceManager_MoveInstance(
-    CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 2) {
-    pArguments->GetReturnValue()->SetUndefined();
-    return;
-  }
-
-  int32_t iFrom = pArguments->GetInt32(0);
-  int32_t iTo = pArguments->GetInt32(1);
-  InstanceManager_MoveInstance(iTo, iFrom);
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  CXFA_Node* pToInstance = GetXFANode()->GetItem(iTo);
-  if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform)
-    pNotify->RunSubformIndexChange(pToInstance);
-
-  CXFA_Node* pFromInstance = GetXFANode()->GetItem(iFrom);
-  if (pFromInstance &&
-      pFromInstance->GetElementType() == XFA_Element::Subform) {
-    pNotify->RunSubformIndexChange(pFromInstance);
-  }
-}
-
-void CJX_Node::Script_InstanceManager_RemoveInstance(
-    CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    pArguments->GetReturnValue()->SetUndefined();
-    return;
-  }
-
-  int32_t iIndex = pArguments->GetInt32(0);
-  int32_t iCount = GetXFANode()->GetCount();
-  if (iIndex < 0 || iIndex >= iCount) {
-    ThrowIndexOutOfBoundsException();
-    return;
-  }
-
-  int32_t iMin = CXFA_OccurData(GetXFANode()->GetOccurNode()).GetMin();
-  if (iCount - 1 < iMin) {
-    ThrowTooManyOccurancesException(L"min");
-    return;
-  }
-
-  CXFA_Node* pRemoveInstance = GetXFANode()->GetItem(iIndex);
-  GetXFANode()->RemoveItem(pRemoveInstance, true);
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (pNotify) {
-    for (int32_t i = iIndex; i < iCount - 1; i++) {
-      CXFA_Node* pSubformInstance = GetXFANode()->GetItem(i);
-      if (pSubformInstance &&
-          pSubformInstance->GetElementType() == XFA_Element::Subform) {
-        pNotify->RunSubformIndexChange(pSubformInstance);
-      }
-    }
-  }
-  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
-  if (!pLayoutPro)
-    return;
-
-  pLayoutPro->AddChangedContainer(
-      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
-}
-
-void CJX_Node::Script_InstanceManager_SetInstances(
-    CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    pArguments->GetReturnValue()->SetUndefined();
-    return;
-  }
-
-  int32_t iDesired = pArguments->GetInt32(0);
-  InstanceManager_SetInstances(iDesired);
-}
-
-void CJX_Node::Script_InstanceManager_AddInstance(
-    CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 0 && argc != 1) {
-    ThrowParamCountMismatchException(L"addInstance");
-    return;
-  }
-
-  bool fFlags = true;
-  if (argc == 1)
-    fFlags = pArguments->GetInt32(0) == 0 ? false : true;
-
-  int32_t iCount = GetXFANode()->GetCount();
-  int32_t iMax = CXFA_OccurData(GetXFANode()->GetOccurNode()).GetMax();
-  if (iMax >= 0 && iCount >= iMax) {
-    ThrowTooManyOccurancesException(L"max");
-    return;
-  }
-
-  CXFA_Node* pNewInstance = GetXFANode()->CreateInstance(fFlags);
-  GetXFANode()->InsertItem(pNewInstance, iCount, iCount, false);
-  pArguments->GetReturnValue()->Assign(
-      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance));
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->RunNodeInitialize(pNewInstance);
-  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
-  if (!pLayoutPro)
-    return;
-
-  pLayoutPro->AddChangedContainer(
-      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
-}
-
-void CJX_Node::Script_InstanceManager_InsertInstance(
-    CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 1 && argc != 2) {
-    ThrowParamCountMismatchException(L"insertInstance");
-    return;
-  }
-
-  int32_t iIndex = pArguments->GetInt32(0);
-  bool bBind = false;
-  if (argc == 2)
-    bBind = pArguments->GetInt32(1) == 0 ? false : true;
-
-  int32_t iCount = GetXFANode()->GetCount();
-  if (iIndex < 0 || iIndex > iCount) {
-    ThrowIndexOutOfBoundsException();
-    return;
-  }
-
-  int32_t iMax = CXFA_OccurData(GetXFANode()->GetOccurNode()).GetMax();
-  if (iMax >= 0 && iCount >= iMax) {
-    ThrowTooManyOccurancesException(L"max");
-    return;
-  }
-
-  CXFA_Node* pNewInstance = GetXFANode()->CreateInstance(bBind);
-  GetXFANode()->InsertItem(pNewInstance, iIndex, iCount, true);
-  pArguments->GetReturnValue()->Assign(
-      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance));
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->RunNodeInitialize(pNewInstance);
-  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
-  if (!pLayoutPro)
-    return;
-
-  pLayoutPro->AddChangedContainer(
-      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
-}
-
 void CJX_Node::Script_Occur_Max(CFXJSE_Value* pValue,
                                 bool bSetting,
                                 XFA_Attribute eAttribute) {
@@ -2622,110 +1402,6 @@
   occurData.SetMin(pValue->ToInteger());
 }
 
-void CJX_Node::Script_Desc_Metadata(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 0 && argc != 1) {
-    ThrowParamCountMismatchException(L"metadata");
-    return;
-  }
-  pArguments->GetReturnValue()->SetString("");
-}
-
-void CJX_Node::Script_Form_FormNodes(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"formNodes");
-    return;
-  }
-
-  CXFA_Node* pDataNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
-  if (!pDataNode) {
-    ThrowArgumentMismatchException();
-    return;
-  }
-
-  std::vector<CXFA_Node*> formItems;
-  CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(GetDocument());
-  pFormNodes->SetArrayNodeList(formItems);
-  pArguments->GetReturnValue()->SetObject(
-      pFormNodes, GetDocument()->GetScriptContext()->GetJseNormalClass());
-}
-
-void CJX_Node::Script_Form_Remerge(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"remerge");
-    return;
-  }
-
-  GetDocument()->DoDataRemerge(true);
-}
-
-void CJX_Node::Script_Form_ExecInitialize(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execInitialize");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize);
-}
-
-void CJX_Node::Script_Form_Recalculate(CFXJSE_Arguments* pArguments) {
-  CXFA_EventParam* pEventParam =
-      GetDocument()->GetScriptContext()->GetEventParam();
-  if (pEventParam->m_eType == XFA_EVENT_Calculate ||
-      pEventParam->m_eType == XFA_EVENT_InitCalculate) {
-    return;
-  }
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"recalculate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-  if (pArguments->GetInt32(0) != 0)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Ready, true);
-}
-
-void CJX_Node::Script_Form_ExecCalculate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execCalculate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return;
-
-  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
-}
-
-void CJX_Node::Script_Form_ExecValidate(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0) {
-    ThrowParamCountMismatchException(L"execValidate");
-    return;
-  }
-
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify) {
-    pArguments->GetReturnValue()->SetBoolean(false);
-    return;
-  }
-
-  int32_t iRet =
-      pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
-  pArguments->GetReturnValue()->SetBoolean(
-      (iRet == XFA_EVENTERROR_Error) ? false : true);
-}
-
 void CJX_Node::Script_Form_Checksum(CFXJSE_Value* pValue,
                                     bool bSetting,
                                     XFA_Attribute eAttribute) {
@@ -2740,58 +1416,6 @@
   pValue->SetString(checksum ? checksum->UTF8Encode().AsStringView() : "");
 }
 
-void CJX_Node::Script_Packet_GetAttribute(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"getAttribute");
-    return;
-  }
-
-  WideString wsAttributeValue;
-  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
-  if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
-    ByteString bsAttributeName = pArguments->GetUTF8String(0);
-    wsAttributeValue = static_cast<CFX_XMLElement*>(pXMLNode)->GetString(
-        WideString::FromUTF8(bsAttributeName.AsStringView()).c_str());
-  }
-
-  pArguments->GetReturnValue()->SetString(
-      wsAttributeValue.UTF8Encode().AsStringView());
-}
-
-void CJX_Node::Script_Packet_SetAttribute(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 2) {
-    ThrowParamCountMismatchException(L"setAttribute");
-    return;
-  }
-
-  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
-  if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
-    ByteString bsValue = pArguments->GetUTF8String(0);
-    ByteString bsName = pArguments->GetUTF8String(1);
-    static_cast<CFX_XMLElement*>(pXMLNode)->SetString(
-        WideString::FromUTF8(bsName.AsStringView()),
-        WideString::FromUTF8(bsValue.AsStringView()));
-  }
-  pArguments->GetReturnValue()->SetNull();
-}
-
-void CJX_Node::Script_Packet_RemoveAttribute(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 1) {
-    ThrowParamCountMismatchException(L"removeAttribute");
-    return;
-  }
-
-  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
-  if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
-    ByteString bsName = pArguments->GetUTF8String(0);
-    WideString wsName = WideString::FromUTF8(bsName.AsStringView());
-    CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode);
-    if (pXMLElement->HasAttribute(wsName.c_str()))
-      pXMLElement->RemoveAttribute(wsName.c_str());
-  }
-  pArguments->GetReturnValue()->SetNull();
-}
-
 void CJX_Node::Script_Packet_Content(CFXJSE_Value* pValue,
                                      bool bSetting,
                                      XFA_Attribute eAttribute) {
@@ -2813,91 +1437,6 @@
   pValue->SetString(wsTextData.UTF8Encode().AsStringView());
 }
 
-void CJX_Node::Script_Source_Next(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"next");
-}
-
-void CJX_Node::Script_Source_CancelBatch(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"cancelBatch");
-}
-
-void CJX_Node::Script_Source_First(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"first");
-}
-
-void CJX_Node::Script_Source_UpdateBatch(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"updateBatch");
-}
-
-void CJX_Node::Script_Source_Previous(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"previous");
-}
-
-void CJX_Node::Script_Source_IsBOF(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"isBOF");
-}
-
-void CJX_Node::Script_Source_IsEOF(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"isEOF");
-}
-
-void CJX_Node::Script_Source_Cancel(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"cancel");
-}
-
-void CJX_Node::Script_Source_Update(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"update");
-}
-
-void CJX_Node::Script_Source_Open(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"open");
-}
-
-void CJX_Node::Script_Source_Delete(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"delete");
-}
-
-void CJX_Node::Script_Source_AddNew(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"addNew");
-}
-
-void CJX_Node::Script_Source_Requery(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"requery");
-}
-
-void CJX_Node::Script_Source_Resync(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"resync");
-}
-
-void CJX_Node::Script_Source_Close(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"close");
-}
-
-void CJX_Node::Script_Source_Last(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"last");
-}
-
-void CJX_Node::Script_Source_HasDataChanged(CFXJSE_Arguments* pArguments) {
-  if (pArguments->GetLength() != 0)
-    ThrowParamCountMismatchException(L"hasDataChanged");
-}
-
 void CJX_Node::Script_Source_Db(CFXJSE_Value* pValue,
                                 bool bSetting,
                                 XFA_Attribute eAttribute) {}
@@ -2939,297 +1478,164 @@
                                      bool bSetting,
                                      XFA_Attribute eAttribute) {}
 
-pdfium::Optional<bool> CJX_Node::TryBoolean(XFA_Attribute eAttr,
-                                            bool bUseDefault) {
-  void* pValue = nullptr;
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  if (GetMapModuleValue(pKey, pValue))
-    return {!!pValue};
-  if (!bUseDefault)
+void CJX_Node::SetWidgetData(std::unique_ptr<CXFA_WidgetData> data) {
+  widget_data_ = std::move(data);
+}
+
+pdfium::Optional<WideString> CJX_Node::TryNamespace() {
+  if (GetXFANode()->IsModelNode() ||
+      GetXFANode()->GetElementType() == XFA_Element::Packet) {
+    CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
+    if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
+      return {};
+
+    return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
+  }
+
+  if (GetXFANode()->GetPacketType() != XFA_PacketType::Datasets)
+    return GetXFANode()->GetModelNode()->JSNode()->TryNamespace();
+
+  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
+  if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
     return {};
 
-  return GetXFANode()->GetDefaultBoolean(eAttr);
-}
-
-bool CJX_Node::SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify) {
-  CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Boolean,
-                                  (void*)(uintptr_t)bValue, bNotify);
-  if (elem)
-    elem->SetString(CXFA_Node::AttributeToName(eAttr), bValue ? L"1" : L"0");
-  return true;
-}
-
-bool CJX_Node::GetBoolean(XFA_Attribute eAttr) {
-  return TryBoolean(eAttr, true).value_or(false);
-}
-
-bool CJX_Node::SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify) {
-  CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Integer,
-                                  (void*)(uintptr_t)iValue, bNotify);
-  if (elem) {
-    elem->SetString(CXFA_Node::AttributeToName(eAttr),
-                    WideString::Format(L"%d", iValue));
+  if (GetXFANode()->GetElementType() == XFA_Element::DataValue &&
+      GetEnum(XFA_Attribute::Contains) == XFA_AttributeEnum::MetaData) {
+    WideString wsNamespace;
+    bool ret = XFA_FDEExtension_ResolveNamespaceQualifier(
+        static_cast<CFX_XMLElement*>(pXMLNode),
+        GetCData(XFA_Attribute::QualifiedName), &wsNamespace);
+    if (!ret)
+      return {};
+    return {wsNamespace};
   }
-  return true;
+  return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
 }
 
-int32_t CJX_Node::GetInteger(XFA_Attribute eAttr) {
-  return TryInteger(eAttr, true).value_or(0);
-}
-
-pdfium::Optional<int32_t> CJX_Node::TryInteger(XFA_Attribute eAttr,
-                                               bool bUseDefault) {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  void* pValue = nullptr;
-  if (GetMapModuleValue(pKey, pValue))
-    return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(pValue))};
-  if (!bUseDefault)
-    return {};
-
-  return GetXFANode()->GetDefaultInteger(eAttr);
-}
-
-pdfium::Optional<XFA_AttributeEnum> CJX_Node::TryEnum(XFA_Attribute eAttr,
-                                                      bool bUseDefault) {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  void* pValue = nullptr;
-  if (GetMapModuleValue(pKey, pValue)) {
-    return {
-        static_cast<XFA_AttributeEnum>(reinterpret_cast<uintptr_t>(pValue))};
-  }
-  if (!bUseDefault)
-    return {};
-
-  return GetXFANode()->GetDefaultEnum(eAttr);
-}
-
-bool CJX_Node::SetEnum(XFA_Attribute eAttr,
-                       XFA_AttributeEnum eValue,
-                       bool bNotify) {
-  CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Enum,
-                                  (void*)(uintptr_t)eValue, bNotify);
-  if (elem) {
-    elem->SetString(CXFA_Node::AttributeToName(eAttr),
-                    CXFA_Node::AttributeEnumToName(eValue));
-  }
-  return true;
-}
-
-XFA_AttributeEnum CJX_Node::GetEnum(XFA_Attribute eAttr) {
-  return TryEnum(eAttr, true).value_or(XFA_AttributeEnum::Unknown);
-}
-
-bool CJX_Node::SetMeasure(XFA_Attribute eAttr,
-                          CXFA_Measurement mValue,
-                          bool bNotify) {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  OnChanging(eAttr, bNotify);
-  SetMapModuleBuffer(pKey, &mValue, sizeof(CXFA_Measurement), nullptr);
-  OnChanged(eAttr, bNotify, false);
-  return true;
-}
-
-pdfium::Optional<CXFA_Measurement> CJX_Node::TryMeasure(
-    XFA_Attribute eAttr,
-    bool bUseDefault) const {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  void* pValue;
-  int32_t iBytes;
-  if (GetMapModuleBuffer(pKey, pValue, iBytes, true) &&
-      iBytes == sizeof(CXFA_Measurement)) {
-    return {*reinterpret_cast<CXFA_Measurement*>(pValue)};
-  }
-  if (!bUseDefault)
-    return {};
-
-  return GetXFANode()->GetDefaultMeasurement(eAttr);
-}
-
-CXFA_Measurement CJX_Node::GetMeasure(XFA_Attribute eAttr) const {
-  return TryMeasure(eAttr, true).value_or(CXFA_Measurement());
-}
-
-WideString CJX_Node::GetCData(XFA_Attribute eAttr) {
-  return TryCData(eAttr, true).value_or(WideString());
-}
-
-bool CJX_Node::SetCData(XFA_Attribute eAttr,
-                        const WideString& wsValue,
-                        bool bNotify,
-                        bool bScriptModify) {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  OnChanging(eAttr, bNotify);
-  if (eAttr == XFA_Attribute::Value) {
-    WideString* pClone = new WideString(wsValue);
-    SetUserData(pKey, pClone, &deleteWideStringCallBack);
-  } else {
-    SetMapModuleString(pKey, wsValue.AsStringView());
-    if (eAttr == XFA_Attribute::Name)
-      GetXFANode()->UpdateNameHash();
-  }
-  OnChanged(eAttr, bNotify, bScriptModify);
-
-  if (!GetXFANode()->IsNeedSavingXMLNode() ||
-      eAttr == XFA_Attribute::QualifiedName ||
-      eAttr == XFA_Attribute::BindingNode) {
-    return true;
-  }
-
-  if (eAttr == XFA_Attribute::Name &&
-      (GetXFANode()->GetElementType() == XFA_Element::DataValue ||
-       GetXFANode()->GetElementType() == XFA_Element::DataGroup)) {
-    return true;
-  }
-
-  auto* elem = static_cast<CFX_XMLElement*>(GetXFANode()->GetXMLMappingNode());
-  if (eAttr == XFA_Attribute::Value) {
-    FX_XMLNODETYPE eXMLType = elem->GetType();
-    switch (eXMLType) {
-      case FX_XMLNODE_Element:
-        if (GetXFANode()->IsAttributeInXML()) {
-          elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
-                          wsValue);
-        } else {
-          bool bDeleteChildren = true;
-          if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) {
-            for (CXFA_Node* pChildDataNode =
-                     GetXFANode()->GetNodeItem(XFA_NODEITEM_FirstChild);
-                 pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem(
-                                     XFA_NODEITEM_NextSibling)) {
-              if (!pChildDataNode->GetBindItems()->empty()) {
-                bDeleteChildren = false;
-                break;
-              }
-            }
-          }
-          if (bDeleteChildren)
-            elem->DeleteChildren();
-
-          elem->SetTextData(wsValue);
-        }
-        break;
-      case FX_XMLNODE_Text:
-        static_cast<CFX_XMLText*>(GetXFANode()->GetXMLMappingNode())
-            ->SetText(wsValue);
-        break;
-      default:
-        ASSERT(0);
-    }
-    return true;
-  }
-  ASSERT(elem->GetType() == FX_XMLNODE_Element);
-
-  WideString wsAttrName = CXFA_Node::AttributeToName(eAttr);
-  if (eAttr == XFA_Attribute::ContentType)
-    wsAttrName = L"xfa:" + wsAttrName;
-
-  elem->SetString(wsAttrName, wsValue);
-  return true;
-}
-
-void CJX_Node::SetAttributeValue(const WideString& wsValue,
-                                 const WideString& wsXMLValue,
-                                 bool bNotify,
-                                 bool bScriptModify) {
-  void* pKey =
-      GetMapKey_Element(GetXFANode()->GetElementType(), XFA_Attribute::Value);
-  OnChanging(XFA_Attribute::Value, bNotify);
-  WideString* pClone = new WideString(wsValue);
-  SetUserData(pKey, pClone, &deleteWideStringCallBack);
-  OnChanged(XFA_Attribute::Value, bNotify, bScriptModify);
-  if (!GetXFANode()->IsNeedSavingXMLNode())
-    return;
-
-  auto* elem = static_cast<CFX_XMLElement*>(GetXFANode()->GetXMLMappingNode());
-  FX_XMLNODETYPE eXMLType = elem->GetType();
-  switch (eXMLType) {
-    case FX_XMLNODE_Element:
-      if (GetXFANode()->IsAttributeInXML()) {
-        elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
-                        wsXMLValue);
-      } else {
-        bool bDeleteChildren = true;
-        if (GetXFANode()->GetPacketType() == XFA_PacketType::Datasets) {
-          for (CXFA_Node* pChildDataNode =
-                   GetXFANode()->GetNodeItem(XFA_NODEITEM_FirstChild);
-               pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem(
-                                   XFA_NODEITEM_NextSibling)) {
-            if (!pChildDataNode->GetBindItems()->empty()) {
-              bDeleteChildren = false;
-              break;
-            }
-          }
-        }
-        if (bDeleteChildren)
-          elem->DeleteChildren();
-
-        elem->SetTextData(wsXMLValue);
-      }
-      break;
-    case FX_XMLNODE_Text:
-      static_cast<CFX_XMLText*>(GetXFANode()->GetXMLMappingNode())
-          ->SetText(wsXMLValue);
-      break;
-    default:
-      ASSERT(0);
-  }
-}
-
-pdfium::Optional<WideString> CJX_Node::TryCData(XFA_Attribute eAttr,
-                                                bool bUseDefault) {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  if (eAttr == XFA_Attribute::Value) {
-    void* pData;
-    int32_t iBytes = 0;
-    WideString* pStr = nullptr;
-    if (GetMapModuleBuffer(pKey, pData, iBytes, true) &&
-        iBytes == sizeof(void*)) {
-      memcpy(&pData, pData, iBytes);
-      pStr = reinterpret_cast<WideString*>(pData);
-    }
-    if (pStr)
-      return {*pStr};
-  } else {
-    WideStringView wsValueC;
-    if (GetMapModuleString(pKey, wsValueC))
-      return {WideString(wsValueC)};
-  }
-  if (!bUseDefault)
-    return {};
-
-  return GetXFANode()->GetDefaultCData(eAttr);
-}
-
-CFX_XMLElement* CJX_Node::SetValue(XFA_Attribute eAttr,
-                                   XFA_AttributeType eType,
-                                   void* pValue,
-                                   bool bNotify) {
-  void* pKey = GetMapKey_Element(GetXFANode()->GetElementType(), eAttr);
-  OnChanging(eAttr, bNotify);
-  SetMapModuleValue(pKey, pValue);
-  OnChanged(eAttr, bNotify, false);
-  if (!GetXFANode()->IsNeedSavingXMLNode())
+CXFA_Node* CJX_Node::GetProperty(int32_t index,
+                                 XFA_Element eProperty,
+                                 bool bCreateProperty) {
+  if (index < 0 || index >= GetXFANode()->PropertyOccuranceCount(eProperty))
     return nullptr;
 
-  auto* elem = static_cast<CFX_XMLElement*>(GetXFANode()->GetXMLMappingNode());
-  ASSERT(elem->GetType() == FX_XMLNODE_Element);
+  int32_t iCount = 0;
+  for (CXFA_Node* pNode = GetXFANode()->GetChildNode(); pNode;
+       pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
+    if (pNode->GetElementType() == eProperty) {
+      iCount++;
+      if (iCount > index)
+        return pNode;
+    }
+  }
+  if (!bCreateProperty)
+    return nullptr;
 
-  return elem;
+  if (GetXFANode()->HasPropertyFlags(eProperty, XFA_PROPERTYFLAG_OneOf)) {
+    for (CXFA_Node* pNode = GetXFANode()->GetChildNode(); pNode;
+         pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
+      if (GetXFANode()->HasPropertyFlags(pNode->GetElementType(),
+                                         XFA_PROPERTYFLAG_OneOf)) {
+        return nullptr;
+      }
+    }
+  }
+
+  CXFA_Node* pNewNode = nullptr;
+  for (; iCount <= index; ++iCount) {
+    pNewNode =
+        GetDocument()->CreateNode(GetXFANode()->GetPacketType(), eProperty);
+    if (!pNewNode)
+      return nullptr;
+    GetXFANode()->InsertChild(pNewNode, nullptr);
+    pNewNode->SetFlag(XFA_NodeFlag_Initialized, true);
+  }
+  return pNewNode;
 }
 
-// TODO(dsinclair): This should not be needed. Nodes should get un-bound when
-// they're deleted instead of us pointing to bad objects.
-void CJX_Node::ReleaseBindingNodes() {
-  for (auto& node : binding_nodes_)
-    node.Release();
+int32_t CJX_Node::execSingleEventByName(const WideStringView& wsEventName,
+                                        XFA_Element eType) {
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return XFA_EVENTERROR_NotExist;
+
+  const XFA_ExecEventParaInfo* eventParaInfo =
+      GetEventParaInfoByName(wsEventName);
+  if (!eventParaInfo)
+    return XFA_EVENTERROR_NotExist;
+
+  switch (eventParaInfo->m_validFlags) {
+    case EventAppliesToo::kNone:
+      return XFA_EVENTERROR_NotExist;
+    case EventAppliesToo::kAll:
+    case EventAppliesToo::kAllNonRecursive:
+      return pNotify->ExecEventByDeepFirst(
+          GetXFANode(), eventParaInfo->m_eventType, false,
+          eventParaInfo->m_validFlags == EventAppliesToo::kAll);
+    case EventAppliesToo::kSubform:
+      if (eType != XFA_Element::Subform)
+        return XFA_EVENTERROR_NotExist;
+
+      return pNotify->ExecEventByDeepFirst(
+          GetXFANode(), eventParaInfo->m_eventType, false, false);
+    case EventAppliesToo::kFieldOrExclusion: {
+      if (eType != XFA_Element::ExclGroup && eType != XFA_Element::Field)
+        return XFA_EVENTERROR_NotExist;
+
+      CXFA_Node* pParentNode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
+      if (pParentNode &&
+          pParentNode->GetElementType() == XFA_Element::ExclGroup) {
+        // TODO(dsinclair): This seems like a bug, we do the same work twice?
+        pNotify->ExecEventByDeepFirst(GetXFANode(), eventParaInfo->m_eventType,
+                                      false, false);
+      }
+      return pNotify->ExecEventByDeepFirst(
+          GetXFANode(), eventParaInfo->m_eventType, false, false);
+    }
+    case EventAppliesToo::kField:
+      if (eType != XFA_Element::Field)
+        return XFA_EVENTERROR_NotExist;
+
+      return pNotify->ExecEventByDeepFirst(
+          GetXFANode(), eventParaInfo->m_eventType, false, false);
+    case EventAppliesToo::kSignature: {
+      CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+      if (!pWidgetData)
+        return XFA_EVENTERROR_NotExist;
+
+      CXFA_Node* pUINode = pWidgetData->GetUIChild();
+      if (pUINode->GetElementType() != XFA_Element::Signature)
+        return XFA_EVENTERROR_NotExist;
+
+      return pNotify->ExecEventByDeepFirst(
+          GetXFANode(), eventParaInfo->m_eventType, false, false);
+    }
+    case EventAppliesToo::kChoiceList: {
+      CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+      if (!pWidgetData)
+        return XFA_EVENTERROR_NotExist;
+
+      CXFA_Node* pUINode = pWidgetData->GetUIChild();
+      if (pUINode->GetElementType() != XFA_Element::ChoiceList ||
+          pWidgetData->IsListBox()) {
+        return XFA_EVENTERROR_NotExist;
+      }
+      return pNotify->ExecEventByDeepFirst(
+          GetXFANode(), eventParaInfo->m_eventType, false, false);
+    }
+  }
+  return XFA_EVENTERROR_NotExist;
 }
 
-bool CJX_Node::SetUserData(void* pKey,
-                           void* pData,
-                           XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
-  SetMapModuleBuffer(pKey, &pData, sizeof(void*),
-                     pCallbackInfo ? pCallbackInfo : &gs_XFADefaultFreeData);
-  return true;
+void CJX_Node::ThrowMissingPropertyException(const WideString& obj,
+                                             const WideString& prop) const {
+  ThrowException(L"'%ls' doesn't have property '%ls'.", obj.c_str(),
+                 prop.c_str());
+}
+
+void CJX_Node::ThrowTooManyOccurancesException(const WideString& obj) const {
+  ThrowException(
+      L"The element [%ls] has violated its allowable number of occurrences.",
+      obj.c_str());
 }
 
 bool CJX_Node::SetContent(const WideString& wsContent,
@@ -3483,407 +1889,3 @@
   }
   return {};
 }
-
-void CJX_Node::SetWidgetData(std::unique_ptr<CXFA_WidgetData> data) {
-  widget_data_ = std::move(data);
-}
-
-void CJX_Node::SetCalcData(std::unique_ptr<CXFA_CalcData> data) {
-  calc_data_ = std::move(data);
-}
-
-std::unique_ptr<CXFA_CalcData> CJX_Node::ReleaseCalcData() {
-  return std::move(calc_data_);
-}
-
-pdfium::Optional<WideString> CJX_Node::TryNamespace() {
-  if (GetXFANode()->IsModelNode() ||
-      GetXFANode()->GetElementType() == XFA_Element::Packet) {
-    CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
-    if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
-      return {};
-
-    return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
-  }
-
-  if (GetXFANode()->GetPacketType() != XFA_PacketType::Datasets)
-    return GetXFANode()->GetModelNode()->JSNode()->TryNamespace();
-
-  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
-  if (!pXMLNode || pXMLNode->GetType() != FX_XMLNODE_Element)
-    return {};
-
-  if (GetXFANode()->GetElementType() == XFA_Element::DataValue &&
-      GetEnum(XFA_Attribute::Contains) == XFA_AttributeEnum::MetaData) {
-    WideString wsNamespace;
-    bool ret = XFA_FDEExtension_ResolveNamespaceQualifier(
-        static_cast<CFX_XMLElement*>(pXMLNode),
-        GetCData(XFA_Attribute::QualifiedName), &wsNamespace);
-    if (!ret)
-      return {};
-    return {wsNamespace};
-  }
-  return {static_cast<CFX_XMLElement*>(pXMLNode)->GetNamespaceURI()};
-}
-
-CXFA_Node* CJX_Node::GetProperty(int32_t index,
-                                 XFA_Element eProperty,
-                                 bool bCreateProperty) {
-  if (index < 0 || index >= GetXFANode()->PropertyOccuranceCount(eProperty))
-    return nullptr;
-
-  CXFA_Node* pNode = GetXFANode()->GetChildNode();
-  int32_t iCount = 0;
-  for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
-    if (pNode->GetElementType() == eProperty) {
-      iCount++;
-      if (iCount > index)
-        return pNode;
-    }
-  }
-  if (!bCreateProperty)
-    return nullptr;
-
-  if (GetXFANode()->HasPropertyFlags(eProperty, XFA_PROPERTYFLAG_OneOf)) {
-    pNode = GetXFANode()->GetChildNode();
-    for (; pNode; pNode = pNode->GetNodeItem(XFA_NODEITEM_NextSibling)) {
-      if (GetXFANode()->HasPropertyFlags(pNode->GetElementType(),
-                                         XFA_PROPERTYFLAG_OneOf)) {
-        return nullptr;
-      }
-    }
-  }
-
-  CXFA_Node* pNewNode = nullptr;
-  for (; iCount <= index; ++iCount) {
-    pNewNode =
-        GetDocument()->CreateNode(GetXFANode()->GetPacketType(), eProperty);
-    if (!pNewNode)
-      return nullptr;
-    GetXFANode()->InsertChild(pNewNode, nullptr);
-    pNewNode->SetFlag(XFA_NodeFlag_Initialized, true);
-  }
-  return pNewNode;
-}
-
-XFA_MAPMODULEDATA* CJX_Node::CreateMapModuleData() {
-  if (!map_module_data_)
-    map_module_data_ = pdfium::MakeUnique<XFA_MAPMODULEDATA>();
-  return map_module_data_.get();
-}
-
-XFA_MAPMODULEDATA* CJX_Node::GetMapModuleData() const {
-  return map_module_data_.get();
-}
-
-void CJX_Node::SetMapModuleValue(void* pKey, void* pValue) {
-  CreateMapModuleData()->m_ValueMap[pKey] = pValue;
-}
-
-bool CJX_Node::GetMapModuleValue(void* pKey, void*& pValue) {
-  for (CXFA_Node* pNode = GetXFANode(); pNode;
-       pNode = pNode->GetTemplateNode()) {
-    XFA_MAPMODULEDATA* pModule = pNode->JSNode()->GetMapModuleData();
-    if (pModule) {
-      auto it = pModule->m_ValueMap.find(pKey);
-      if (it != pModule->m_ValueMap.end()) {
-        pValue = it->second;
-        return true;
-      }
-    }
-    if (pNode->GetPacketType() == XFA_PacketType::Datasets)
-      break;
-  }
-  return false;
-}
-
-void CJX_Node::SetMapModuleString(void* pKey, const WideStringView& wsValue) {
-  SetMapModuleBuffer(pKey, (void*)wsValue.unterminated_c_str(),
-                     wsValue.GetLength() * sizeof(wchar_t), nullptr);
-}
-
-bool CJX_Node::GetMapModuleString(void* pKey, WideStringView& wsValue) {
-  void* pValue;
-  int32_t iBytes;
-  if (!GetMapModuleBuffer(pKey, pValue, iBytes, true))
-    return false;
-
-  // Defensive measure: no out-of-bounds pointers even if zero length.
-  int32_t iChars = iBytes / sizeof(wchar_t);
-  wsValue = WideStringView(iChars ? (const wchar_t*)pValue : nullptr, iChars);
-  return true;
-}
-
-void CJX_Node::SetMapModuleBuffer(void* pKey,
-                                  void* pValue,
-                                  int32_t iBytes,
-                                  XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
-  XFA_MAPDATABLOCK*& pBuffer = CreateMapModuleData()->m_BufferMap[pKey];
-  if (!pBuffer) {
-    pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
-        FX_Alloc(uint8_t, sizeof(XFA_MAPDATABLOCK) + iBytes));
-  } else if (pBuffer->iBytes != iBytes) {
-    if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
-      pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
-
-    pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
-        FX_Realloc(uint8_t, pBuffer, sizeof(XFA_MAPDATABLOCK) + iBytes));
-  } else if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) {
-    pBuffer->pCallbackInfo->pFree(
-        *reinterpret_cast<void**>(pBuffer->GetData()));
-  }
-  if (!pBuffer)
-    return;
-
-  pBuffer->pCallbackInfo = pCallbackInfo;
-  pBuffer->iBytes = iBytes;
-  memcpy(pBuffer->GetData(), pValue, iBytes);
-}
-
-bool CJX_Node::GetMapModuleBuffer(void* pKey,
-                                  void*& pValue,
-                                  int32_t& iBytes,
-                                  bool bProtoAlso) const {
-  XFA_MAPDATABLOCK* pBuffer = nullptr;
-  for (const CXFA_Node* pNode = GetXFANode(); pNode;
-       pNode = pNode->GetTemplateNode()) {
-    XFA_MAPMODULEDATA* pModule = pNode->JSNode()->GetMapModuleData();
-    if (pModule) {
-      auto it = pModule->m_BufferMap.find(pKey);
-      if (it != pModule->m_BufferMap.end()) {
-        pBuffer = it->second;
-        break;
-      }
-    }
-    if (!bProtoAlso || pNode->GetPacketType() == XFA_PacketType::Datasets)
-      break;
-  }
-  if (!pBuffer)
-    return false;
-
-  pValue = pBuffer->GetData();
-  iBytes = pBuffer->iBytes;
-  return true;
-}
-
-bool CJX_Node::HasMapModuleKey(void* pKey) {
-  XFA_MAPMODULEDATA* pModule = GetXFANode()->JSNode()->GetMapModuleData();
-  return pModule && (pdfium::ContainsKey(pModule->m_ValueMap, pKey) ||
-                     pdfium::ContainsKey(pModule->m_BufferMap, pKey));
-}
-
-void CJX_Node::ClearMapModuleBuffer() {
-  XFA_MAPMODULEDATA* pModule = GetMapModuleData();
-  if (!pModule)
-    return;
-
-  for (auto& pair : pModule->m_BufferMap) {
-    XFA_MAPDATABLOCK* pBuffer = pair.second;
-    if (pBuffer) {
-      if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
-        pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
-
-      FX_Free(pBuffer);
-    }
-  }
-  pModule->m_BufferMap.clear();
-  pModule->m_ValueMap.clear();
-}
-
-void CJX_Node::RemoveMapModuleKey(void* pKey) {
-  ASSERT(pKey);
-
-  XFA_MAPMODULEDATA* pModule = GetMapModuleData();
-  if (!pModule)
-    return;
-
-  auto it = pModule->m_BufferMap.find(pKey);
-  if (it != pModule->m_BufferMap.end()) {
-    XFA_MAPDATABLOCK* pBuffer = it->second;
-    if (pBuffer) {
-      if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
-        pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
-
-      FX_Free(pBuffer);
-    }
-    pModule->m_BufferMap.erase(it);
-  }
-  pModule->m_ValueMap.erase(pKey);
-  return;
-}
-
-void CJX_Node::MergeAllData(CXFA_Node* pDstModule) {
-  XFA_MAPMODULEDATA* pDstModuleData =
-      pDstModule->JSNode()->CreateMapModuleData();
-  XFA_MAPMODULEDATA* pSrcModuleData = GetMapModuleData();
-  if (!pSrcModuleData)
-    return;
-
-  for (const auto& pair : pSrcModuleData->m_ValueMap)
-    pDstModuleData->m_ValueMap[pair.first] = pair.second;
-
-  for (const auto& pair : pSrcModuleData->m_BufferMap) {
-    XFA_MAPDATABLOCK* pSrcBuffer = pair.second;
-    XFA_MAPDATABLOCK*& pDstBuffer = pDstModuleData->m_BufferMap[pair.first];
-    if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree &&
-        !pSrcBuffer->pCallbackInfo->pCopy) {
-      if (pDstBuffer) {
-        pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
-        pDstModuleData->m_BufferMap.erase(pair.first);
-      }
-      continue;
-    }
-    if (!pDstBuffer) {
-      pDstBuffer = (XFA_MAPDATABLOCK*)FX_Alloc(
-          uint8_t, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
-    } else if (pDstBuffer->iBytes != pSrcBuffer->iBytes) {
-      if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
-        pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
-      }
-      pDstBuffer = (XFA_MAPDATABLOCK*)FX_Realloc(
-          uint8_t, pDstBuffer, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
-    } else if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
-      pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
-    }
-    if (!pDstBuffer)
-      continue;
-
-    pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo;
-    pDstBuffer->iBytes = pSrcBuffer->iBytes;
-    memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), pSrcBuffer->iBytes);
-    if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pCopy) {
-      pDstBuffer->pCallbackInfo->pCopy(*(void**)pDstBuffer->GetData());
-    }
-  }
-}
-
-void CJX_Node::MoveBufferMapData(CXFA_Node* pDstModule) {
-  if (!pDstModule)
-    return;
-
-  bool bNeedMove = true;
-  if (pDstModule->GetElementType() != GetXFANode()->GetElementType())
-    bNeedMove = false;
-
-  if (bNeedMove)
-    pDstModule->JSNode()->SetCalcData(ReleaseCalcData());
-  if (!pDstModule->IsNodeV())
-    return;
-
-  WideString wsValue = pDstModule->JSNode()->GetContent(false);
-  WideString wsFormatValue(wsValue);
-  CXFA_WidgetData* pWidgetData = pDstModule->GetContainerWidgetData();
-  if (pWidgetData)
-    wsFormatValue = pWidgetData->GetFormatDataValue(wsValue);
-
-  pDstModule->JSNode()->SetContent(wsValue, wsFormatValue, true, true, true);
-}
-
-void CJX_Node::MoveBufferMapData(CXFA_Node* pSrcModule, CXFA_Node* pDstModule) {
-  if (!pSrcModule || !pDstModule)
-    return;
-
-  CXFA_Node* pSrcChild = pSrcModule->GetNodeItem(XFA_NODEITEM_FirstChild);
-  CXFA_Node* pDstChild = pDstModule->GetNodeItem(XFA_NODEITEM_FirstChild);
-  while (pSrcChild && pDstChild) {
-    MoveBufferMapData(pSrcChild, pDstChild);
-
-    pSrcChild = pSrcChild->GetNodeItem(XFA_NODEITEM_NextSibling);
-    pDstChild = pDstChild->GetNodeItem(XFA_NODEITEM_NextSibling);
-  }
-  pSrcModule->JSNode()->MoveBufferMapData(pDstModule);
-}
-
-int32_t CJX_Node::execSingleEventByName(const WideStringView& wsEventName,
-                                        XFA_Element eType) {
-  const XFA_ExecEventParaInfo* eventParaInfo =
-      GetEventParaInfoByName(wsEventName);
-  if (!eventParaInfo)
-    return XFA_EVENTERROR_NotExist;
-
-  uint32_t validFlags = eventParaInfo->m_validFlags;
-  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
-  if (!pNotify)
-    return XFA_EVENTERROR_NotExist;
-
-  if (validFlags == 1) {
-    return pNotify->ExecEventByDeepFirst(GetXFANode(),
-                                         eventParaInfo->m_eventType);
-  }
-
-  if (validFlags == 2) {
-    return pNotify->ExecEventByDeepFirst(
-        GetXFANode(), eventParaInfo->m_eventType, false, false);
-  }
-
-  if (validFlags == 3) {
-    if (eType != XFA_Element::Subform)
-      return XFA_EVENTERROR_NotExist;
-
-    return pNotify->ExecEventByDeepFirst(
-        GetXFANode(), eventParaInfo->m_eventType, false, false);
-  }
-
-  if (validFlags == 4) {
-    if (eType != XFA_Element::ExclGroup && eType != XFA_Element::Field)
-      return XFA_EVENTERROR_NotExist;
-
-    CXFA_Node* pParentNode = GetXFANode()->GetNodeItem(XFA_NODEITEM_Parent);
-    if (pParentNode &&
-        pParentNode->GetElementType() == XFA_Element::ExclGroup) {
-      pNotify->ExecEventByDeepFirst(GetXFANode(), eventParaInfo->m_eventType,
-                                    false, false);
-    }
-    return pNotify->ExecEventByDeepFirst(
-        GetXFANode(), eventParaInfo->m_eventType, false, false);
-  }
-
-  if (validFlags == 5) {
-    if (eType != XFA_Element::Field)
-      return XFA_EVENTERROR_NotExist;
-
-    return pNotify->ExecEventByDeepFirst(
-        GetXFANode(), eventParaInfo->m_eventType, false, false);
-  }
-
-  if (validFlags == 6) {
-    CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-    if (!pWidgetData)
-      return XFA_EVENTERROR_NotExist;
-
-    CXFA_Node* pUINode = pWidgetData->GetUIChild();
-    if (pUINode->GetElementType() != XFA_Element::Signature)
-      return XFA_EVENTERROR_NotExist;
-
-    return pNotify->ExecEventByDeepFirst(
-        GetXFANode(), eventParaInfo->m_eventType, false, false);
-  }
-
-  if (validFlags == 7) {
-    CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
-    if (!pWidgetData)
-      return XFA_EVENTERROR_NotExist;
-
-    CXFA_Node* pUINode = pWidgetData->GetUIChild();
-    if (pUINode->GetElementType() != XFA_Element::ChoiceList ||
-        pWidgetData->IsListBox()) {
-      return XFA_EVENTERROR_NotExist;
-    }
-    return pNotify->ExecEventByDeepFirst(
-        GetXFANode(), eventParaInfo->m_eventType, false, false);
-  }
-
-  return XFA_EVENTERROR_NotExist;
-}
-
-void CJX_Node::ThrowMissingPropertyException(const WideString& obj,
-                                             const WideString& prop) const {
-  ThrowException(L"'%s' doesn't have property '%s'.", obj.c_str(),
-                 prop.c_str());
-}
-
-void CJX_Node::ThrowTooManyOccurancesException(const WideString& obj) const {
-  ThrowException(
-      L"The element [%s] has violated its allowable number of occurrences.",
-      obj.c_str());
-}
diff --git a/fxjs/cjx_node.h b/fxjs/cjx_node.h
index ba1d752..7ccf8b1 100644
--- a/fxjs/cjx_node.h
+++ b/fxjs/cjx_node.h
@@ -12,33 +12,22 @@
 #include <vector>
 
 #include "core/fxcrt/unowned_ptr.h"
+#include "fxjs/CJX_Define.h"
 #include "fxjs/cjx_object.h"
+#include "fxjs/xfa/cjx_tree.h"
 #include "xfa/fxfa/fxfa_basic.h"
 
-typedef void (*PD_CALLBACK_FREEDATA)(void* pData);
-typedef void (*PD_CALLBACK_DUPLICATEDATA)(void*& pData);
-
-struct XFA_MAPDATABLOCKCALLBACKINFO {
-  PD_CALLBACK_FREEDATA pFree;
-  PD_CALLBACK_DUPLICATEDATA pCopy;
-};
-
 enum XFA_SOM_MESSAGETYPE {
   XFA_SOM_ValidationMessage,
   XFA_SOM_FormatMessage,
   XFA_SOM_MandatoryMessage
 };
 
-class CFX_XMLElement;
-class CFXJSE_Arguments;
-class CXFA_CalcData;
 class CXFA_LayoutItem;
 class CXFA_Node;
 class CXFA_WidgetData;
 
-struct XFA_MAPMODULEDATA;
-
-class CJX_Node : public CJX_Object {
+class CJX_Node : public CJX_Tree {
  public:
   explicit CJX_Node(CXFA_Node* node);
   ~CJX_Node() override;
@@ -46,26 +35,6 @@
   CXFA_Node* GetXFANode();
   const CXFA_Node* GetXFANode() const;
 
-  bool HasAttribute(XFA_Attribute eAttr);
-  bool SetAttribute(XFA_Attribute eAttr,
-                    const WideStringView& wsValue,
-                    bool bNotify);
-  bool SetAttribute(const WideStringView& wsAttr,
-                    const WideStringView& wsValue,
-                    bool bNotify);
-  WideString GetAttribute(const WideStringView& attr);
-  WideString GetAttribute(XFA_Attribute attr);
-  pdfium::Optional<WideString> TryAttribute(const WideStringView& wsAttr,
-                                            bool bUseDefault);
-  pdfium::Optional<WideString> TryAttribute(XFA_Attribute eAttr,
-                                            bool bUseDefault);
-
-  void SetAttributeValue(const WideString& wsValue,
-                         const WideString& wsXMLValue,
-                         bool bNotify,
-                         bool bScriptModify);
-  void RemoveAttribute(const WideStringView& wsAttr);
-
   CXFA_Node* GetProperty(int32_t index,
                          XFA_Element eType,
                          bool bCreateProperty);
@@ -78,67 +47,17 @@
                   bool bSyncData);
   WideString GetContent(bool bScriptModify);
 
-  pdfium::Optional<int32_t> TryInteger(XFA_Attribute eAttr, bool bUseDefault);
-  bool SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify);
-  int32_t GetInteger(XFA_Attribute eAttr);
-
-  pdfium::Optional<WideString> TryCData(XFA_Attribute eAttr, bool bUseDefault);
-  bool SetCData(XFA_Attribute eAttr,
-                const WideString& wsValue,
-                bool bNotify,
-                bool bScriptModify);
-  WideString GetCData(XFA_Attribute eAttr);
-
-  pdfium::Optional<XFA_AttributeEnum> TryEnum(XFA_Attribute eAttr,
-                                              bool bUseDefault);
-  bool SetEnum(XFA_Attribute eAttr, XFA_AttributeEnum eValue, bool bNotify);
-  XFA_AttributeEnum GetEnum(XFA_Attribute eAttr);
-
-  pdfium::Optional<bool> TryBoolean(XFA_Attribute eAttr, bool bUseDefault);
-  bool SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify);
-  bool GetBoolean(XFA_Attribute eAttr);
-
-  pdfium::Optional<CXFA_Measurement> TryMeasure(XFA_Attribute eAttr,
-                                                bool bUseDefault) const;
-  bool SetMeasure(XFA_Attribute eAttr, CXFA_Measurement mValue, bool bNotify);
-  CXFA_Measurement GetMeasure(XFA_Attribute eAttr) const;
-
-  void SetBindingNodes(std::vector<UnownedPtr<CXFA_Node>> nodes) {
-    binding_nodes_ = std::move(nodes);
-  }
-  std::vector<UnownedPtr<CXFA_Node>>* GetBindingNodes() {
-    return &binding_nodes_;
-  }
-  void ReleaseBindingNodes();
-
-  void SetBindingNode(CXFA_Node* node) {
-    binding_nodes_.clear();
-    if (node)
-      binding_nodes_.emplace_back(node);
-  }
-  CXFA_Node* GetBindingNode() const {
-    if (binding_nodes_.empty())
-      return nullptr;
-    return binding_nodes_[0].Get();
-  }
-
   void SetWidgetData(std::unique_ptr<CXFA_WidgetData> data);
   CXFA_WidgetData* GetWidgetData() const { return widget_data_.get(); }
 
   void SetLayoutItem(CXFA_LayoutItem* item) { layout_item_ = item; }
   CXFA_LayoutItem* GetLayoutItem() const { return layout_item_.Get(); }
 
-  void SetCalcData(std::unique_ptr<CXFA_CalcData> data);
-  CXFA_CalcData* GetCalcData() const { return calc_data_.get(); }
-  std::unique_ptr<CXFA_CalcData> ReleaseCalcData();
-
   void SetCalcRecursionCount(size_t count) { calc_recursion_count_ = count; }
   size_t GetCalcRecursionCount() const { return calc_recursion_count_; }
 
   pdfium::Optional<WideString> TryNamespace();
 
-  void MergeAllData(CXFA_Node* pDstModule);
-
   void ThrowMissingPropertyException(const WideString& obj,
                                      const WideString& prop) const;
   void ThrowTooManyOccurancesException(const WideString& obj) const;
@@ -147,41 +66,18 @@
   int32_t InstanceManager_SetInstances(int32_t iDesired);
   int32_t InstanceManager_MoveInstance(int32_t iTo, int32_t iFrom);
 
-  void Script_TreeClass_ResolveNode(CFXJSE_Arguments* pArguments);
-  void Script_TreeClass_ResolveNodes(CFXJSE_Arguments* pArguments);
+  JS_METHOD(applyXSL, CJX_Node);
+  JS_METHOD(assignNode, CJX_Node);
+  JS_METHOD(clone, CJX_Node);
+  JS_METHOD(getAttribute, CJX_Node);
+  JS_METHOD(getElement, CJX_Node);
+  JS_METHOD(isPropertySpecified, CJX_Node);
+  JS_METHOD(loadXML, CJX_Node);
+  JS_METHOD(saveFilteredXML, CJX_Node);
+  JS_METHOD(saveXML, CJX_Node);
+  JS_METHOD(setAttribute, CJX_Node);
+  JS_METHOD(setElement, CJX_Node);
 
-  void Script_TreeClass_All(CFXJSE_Value* pValue,
-                            bool bSetting,
-                            XFA_Attribute eAttribute);
-  void Script_TreeClass_Nodes(CFXJSE_Value* pValue,
-                              bool bSetting,
-                              XFA_Attribute eAttribute);
-  void Script_TreeClass_ClassAll(CFXJSE_Value* pValue,
-                                 bool bSetting,
-                                 XFA_Attribute eAttribute);
-  void Script_TreeClass_Parent(CFXJSE_Value* pValue,
-                               bool bSetting,
-                               XFA_Attribute eAttribute);
-  void Script_TreeClass_Index(CFXJSE_Value* pValue,
-                              bool bSetting,
-                              XFA_Attribute eAttribute);
-  void Script_TreeClass_ClassIndex(CFXJSE_Value* pValue,
-                                   bool bSetting,
-                                   XFA_Attribute eAttribute);
-  void Script_TreeClass_SomExpression(CFXJSE_Value* pValue,
-                                      bool bSetting,
-                                      XFA_Attribute eAttribute);
-  void Script_NodeClass_ApplyXSL(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_AssignNode(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_Clone(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_GetAttribute(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_GetElement(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_IsPropertySpecified(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_LoadXML(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_SaveFilteredXML(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_SaveXML(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_SetAttribute(CFXJSE_Arguments* pArguments);
-  void Script_NodeClass_SetElement(CFXJSE_Arguments* pArguments);
   void Script_NodeClass_Ns(CFXJSE_Value* pValue,
                            bool bSetting,
                            XFA_Attribute eAttribute);
@@ -197,19 +93,12 @@
   void Script_NodeClass_OneOfChild(CFXJSE_Value* pValue,
                                    bool bSetting,
                                    XFA_Attribute eAttribute);
-  void Script_ContainerClass_GetDelta(CFXJSE_Arguments* pArguments);
-  void Script_ContainerClass_GetDeltas(CFXJSE_Arguments* pArguments);
-  void Script_ModelClass_ClearErrorList(CFXJSE_Arguments* pArguments);
-  void Script_ModelClass_CreateNode(CFXJSE_Arguments* pArguments);
-  void Script_ModelClass_IsCompatibleNS(CFXJSE_Arguments* pArguments);
   void Script_ModelClass_Context(CFXJSE_Value* pValue,
                                  bool bSetting,
                                  XFA_Attribute eAttribute);
   void Script_ModelClass_AliasNode(CFXJSE_Value* pValue,
                                    bool bSetting,
                                    XFA_Attribute eAttribute);
-  void Script_WsdlConnection_Execute(CFXJSE_Arguments* pArguments);
-  void Script_Delta_Restore(CFXJSE_Arguments* pArguments);
   void Script_Delta_CurrentValue(CFXJSE_Value* pValue,
                                  bool bSetting,
                                  XFA_Attribute eAttribute);
@@ -300,19 +189,6 @@
   void Script_Field_SelectedIndex(CFXJSE_Value* pValue,
                                   bool bSetting,
                                   XFA_Attribute eAttribute);
-  void Script_Field_ClearItems(CFXJSE_Arguments* pArguments);
-  void Script_Field_ExecEvent(CFXJSE_Arguments* pArguments);
-  void Script_Field_ExecInitialize(CFXJSE_Arguments* pArguments);
-  void Script_Field_DeleteItem(CFXJSE_Arguments* pArguments);
-  void Script_Field_GetSaveItem(CFXJSE_Arguments* pArguments);
-  void Script_Field_BoundItem(CFXJSE_Arguments* pArguments);
-  void Script_Field_GetItemState(CFXJSE_Arguments* pArguments);
-  void Script_Field_ExecCalculate(CFXJSE_Arguments* pArguments);
-  void Script_Field_SetItems(CFXJSE_Arguments* pArguments);
-  void Script_Field_GetDisplayItem(CFXJSE_Arguments* pArguments);
-  void Script_Field_SetItemState(CFXJSE_Arguments* pArguments);
-  void Script_Field_AddItem(CFXJSE_Arguments* pArguments);
-  void Script_Field_ExecValidate(CFXJSE_Arguments* pArguments);
   void Script_ExclGroup_DefaultAndRawValue(CFXJSE_Value* pValue,
                                            bool bSetting,
                                            XFA_Attribute eAttribute);
@@ -322,30 +198,13 @@
   void Script_ExclGroup_Transient(CFXJSE_Value* pValue,
                                   bool bSetting,
                                   XFA_Attribute eAttribute);
-  void Script_ExclGroup_ExecEvent(CFXJSE_Arguments* pArguments);
-  void Script_ExclGroup_SelectedMember(CFXJSE_Arguments* pArguments);
-  void Script_ExclGroup_ExecInitialize(CFXJSE_Arguments* pArguments);
-  void Script_ExclGroup_ExecCalculate(CFXJSE_Arguments* pArguments);
-  void Script_ExclGroup_ExecValidate(CFXJSE_Arguments* pArguments);
+
   void Script_Subform_InstanceManager(CFXJSE_Value* pValue,
                                       bool bSetting,
                                       XFA_Attribute eAttribute);
   void Script_Subform_Locale(CFXJSE_Value* pValue,
                              bool bSetting,
                              XFA_Attribute eAttribute);
-  void Script_Subform_ExecEvent(CFXJSE_Arguments* pArguments);
-  void Script_Subform_ExecInitialize(CFXJSE_Arguments* pArguments);
-  void Script_Subform_ExecCalculate(CFXJSE_Arguments* pArguments);
-  void Script_Subform_ExecValidate(CFXJSE_Arguments* pArguments);
-  void Script_Subform_GetInvalidObjects(CFXJSE_Arguments* pArguments);
-  void Script_Template_FormNodes(CFXJSE_Arguments* pArguments);
-  void Script_Template_Remerge(CFXJSE_Arguments* pArguments);
-  void Script_Template_ExecInitialize(CFXJSE_Arguments* pArguments);
-  void Script_Template_CreateNode(CFXJSE_Arguments* pArguments);
-  void Script_Template_Recalculate(CFXJSE_Arguments* pArguments);
-  void Script_Template_ExecCalculate(CFXJSE_Arguments* pArguments);
-  void Script_Template_ExecValidate(CFXJSE_Arguments* pArguments);
-  void Script_Manifest_Evaluate(CFXJSE_Arguments* pArguments);
   void Script_InstanceManager_Count(CFXJSE_Value* pValue,
                                     bool bSetting,
                                     XFA_Attribute eAttribute);
@@ -355,50 +214,22 @@
   void Script_InstanceManager_Min(CFXJSE_Value* pValue,
                                   bool bSetting,
                                   XFA_Attribute eAttribute);
-  void Script_InstanceManager_MoveInstance(CFXJSE_Arguments* pArguments);
-  void Script_InstanceManager_RemoveInstance(CFXJSE_Arguments* pArguments);
-  void Script_InstanceManager_SetInstances(CFXJSE_Arguments* pArguments);
-  void Script_InstanceManager_AddInstance(CFXJSE_Arguments* pArguments);
-  void Script_InstanceManager_InsertInstance(CFXJSE_Arguments* pArguments);
+
   void Script_Occur_Max(CFXJSE_Value* pValue,
                         bool bSetting,
                         XFA_Attribute eAttribute);
   void Script_Occur_Min(CFXJSE_Value* pValue,
                         bool bSetting,
                         XFA_Attribute eAttribute);
-  void Script_Desc_Metadata(CFXJSE_Arguments* pArguments);
-  void Script_Form_FormNodes(CFXJSE_Arguments* pArguments);
-  void Script_Form_Remerge(CFXJSE_Arguments* pArguments);
-  void Script_Form_ExecInitialize(CFXJSE_Arguments* pArguments);
-  void Script_Form_Recalculate(CFXJSE_Arguments* pArguments);
-  void Script_Form_ExecCalculate(CFXJSE_Arguments* pArguments);
-  void Script_Form_ExecValidate(CFXJSE_Arguments* pArguments);
+
   void Script_Form_Checksum(CFXJSE_Value* pValue,
                             bool bSetting,
                             XFA_Attribute eAttribute);
-  void Script_Packet_GetAttribute(CFXJSE_Arguments* pArguments);
-  void Script_Packet_SetAttribute(CFXJSE_Arguments* pArguments);
-  void Script_Packet_RemoveAttribute(CFXJSE_Arguments* pArguments);
+
   void Script_Packet_Content(CFXJSE_Value* pValue,
                              bool bSetting,
                              XFA_Attribute eAttribute);
-  void Script_Source_Next(CFXJSE_Arguments* pArguments);
-  void Script_Source_CancelBatch(CFXJSE_Arguments* pArguments);
-  void Script_Source_First(CFXJSE_Arguments* pArguments);
-  void Script_Source_UpdateBatch(CFXJSE_Arguments* pArguments);
-  void Script_Source_Previous(CFXJSE_Arguments* pArguments);
-  void Script_Source_IsBOF(CFXJSE_Arguments* pArguments);
-  void Script_Source_IsEOF(CFXJSE_Arguments* pArguments);
-  void Script_Source_Cancel(CFXJSE_Arguments* pArguments);
-  void Script_Source_Update(CFXJSE_Arguments* pArguments);
-  void Script_Source_Open(CFXJSE_Arguments* pArguments);
-  void Script_Source_Delete(CFXJSE_Arguments* pArguments);
-  void Script_Source_AddNew(CFXJSE_Arguments* pArguments);
-  void Script_Source_Requery(CFXJSE_Arguments* pArguments);
-  void Script_Source_Resync(CFXJSE_Arguments* pArguments);
-  void Script_Source_Close(CFXJSE_Arguments* pArguments);
-  void Script_Source_Last(CFXJSE_Arguments* pArguments);
-  void Script_Source_HasDataChanged(CFXJSE_Arguments* pArguments);
+
   void Script_Source_Db(CFXJSE_Value* pValue,
                         bool bSetting,
                         XFA_Attribute eAttribute);
@@ -421,58 +252,15 @@
                                bool bSetting,
                                XFA_Attribute eAttribute);
 
- private:
-  bool SetUserData(void* pKey,
-                   void* pData,
-                   XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo);
-
-  void ResolveNodeList(CFXJSE_Value* pValue,
-                       WideString wsExpression,
-                       uint32_t dwFlag,
-                       CXFA_Node* refNode);
-
-  void OnChanged(XFA_Attribute eAttr, bool bNotify, bool bScriptModify);
-  void OnChanging(XFA_Attribute eAttr, bool bNotify);
-  void SendAttributeChangeMessage(XFA_Attribute eAttribute, bool bScriptModify);
-
-  // Returns a pointer to the XML node that needs to be updated with the new
-  // attribute value. |nullptr| if no update is needed.
-  CFX_XMLElement* SetValue(XFA_Attribute eAttr,
-                           XFA_AttributeType eType,
-                           void* pValue,
-                           bool bNotify);
-
-  bool TryUserData(void* pKey, void*& pData, bool bProtoAlso);
-
-  XFA_MAPMODULEDATA* CreateMapModuleData();
-  XFA_MAPMODULEDATA* GetMapModuleData() const;
-  void SetMapModuleValue(void* pKey, void* pValue);
-  bool GetMapModuleValue(void* pKey, void*& pValue);
-  void SetMapModuleString(void* pKey, const WideStringView& wsValue);
-  bool GetMapModuleString(void* pKey, WideStringView& wsValue);
-  void SetMapModuleBuffer(void* pKey,
-                          void* pValue,
-                          int32_t iBytes,
-                          XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo);
-  bool GetMapModuleBuffer(void* pKey,
-                          void*& pValue,
-                          int32_t& iBytes,
-                          bool bProtoAlso) const;
-  bool HasMapModuleKey(void* pKey);
-  void ClearMapModuleBuffer();
-  void RemoveMapModuleKey(void* pKey);
-  void MoveBufferMapData(CXFA_Node* pDstModule);
-  void MoveBufferMapData(CXFA_Node* pSrcModule, CXFA_Node* pDstModule);
-
+ protected:
   int32_t execSingleEventByName(const WideStringView& wsEventName,
                                 XFA_Element eType);
 
-  std::unique_ptr<XFA_MAPMODULEDATA> map_module_data_;
+ private:
   std::unique_ptr<CXFA_WidgetData> widget_data_;
-  std::unique_ptr<CXFA_CalcData> calc_data_;
   UnownedPtr<CXFA_LayoutItem> layout_item_;
-  std::vector<UnownedPtr<CXFA_Node>> binding_nodes_;
   size_t calc_recursion_count_ = 0;
+  static const CJX_MethodSpec MethodSpecs[];
 };
 
 #endif  // FXJS_CJX_NODE_H_
diff --git a/fxjs/cjx_nodelist.cpp b/fxjs/cjx_nodelist.cpp
deleted file mode 100644
index badd71c..0000000
--- a/fxjs/cjx_nodelist.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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/cjx_nodelist.h"
-
-#include "fxjs/cfxjse_arguments.h"
-#include "fxjs/cfxjse_engine.h"
-#include "fxjs/cfxjse_value.h"
-#include "xfa/fxfa/parser/cxfa_document.h"
-#include "xfa/fxfa/parser/cxfa_node.h"
-#include "xfa/fxfa/parser/cxfa_nodelist.h"
-
-CJX_NodeList::CJX_NodeList(CXFA_NodeList* list) : CJX_Object(list) {}
-
-CJX_NodeList::~CJX_NodeList() {}
-
-CXFA_NodeList* CJX_NodeList::GetXFANodeList() {
-  return static_cast<CXFA_NodeList*>(GetXFAObject());
-}
-
-void CJX_NodeList::Script_ListClass_Append(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 1) {
-    ThrowParamCountMismatchException(L"append");
-    return;
-  }
-
-  auto* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
-  if (!pNode) {
-    ThrowArgumentMismatchException();
-    return;
-  }
-  GetXFANodeList()->Append(pNode);
-}
-
-void CJX_NodeList::Script_ListClass_Insert(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 2) {
-    ThrowParamCountMismatchException(L"insert");
-    return;
-  }
-
-  auto* pNewNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
-  auto* pBeforeNode = static_cast<CXFA_Node*>(pArguments->GetObject(1));
-  if (!pNewNode) {
-    ThrowArgumentMismatchException();
-    return;
-  }
-  GetXFANodeList()->Insert(pNewNode, pBeforeNode);
-}
-
-void CJX_NodeList::Script_ListClass_Remove(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 1) {
-    ThrowParamCountMismatchException(L"remove");
-    return;
-  }
-
-  auto* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
-  if (!pNode) {
-    ThrowArgumentMismatchException();
-    return;
-  }
-  GetXFANodeList()->Remove(pNode);
-}
-
-void CJX_NodeList::Script_ListClass_Item(CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 1) {
-    ThrowParamCountMismatchException(L"item");
-    return;
-  }
-
-  int32_t iIndex = pArguments->GetInt32(0);
-  if (iIndex < 0 || iIndex >= GetXFANodeList()->GetLength()) {
-    ThrowIndexOutOfBoundsException();
-    return;
-  }
-  pArguments->GetReturnValue()->Assign(
-      GetDocument()->GetScriptContext()->GetJSValueFromMap(
-          GetXFANodeList()->Item(iIndex)));
-}
-
-void CJX_NodeList::Script_TreelistClass_NamedItem(
-    CFXJSE_Arguments* pArguments) {
-  int32_t argc = pArguments->GetLength();
-  if (argc != 1) {
-    ThrowParamCountMismatchException(L"namedItem");
-    return;
-  }
-
-  ByteString szName = pArguments->GetUTF8String(0);
-  CXFA_Node* pNode = GetXFANodeList()->NamedItem(
-      WideString::FromUTF8(szName.AsStringView()).AsStringView());
-  if (!pNode)
-    return;
-
-  pArguments->GetReturnValue()->Assign(
-      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode));
-}
-
-void CJX_NodeList::Script_ListClass_Length(CFXJSE_Value* pValue,
-                                           bool bSetting,
-                                           XFA_Attribute eAttribute) {
-  if (bSetting) {
-    ThrowInvalidPropertyException();
-    return;
-  }
-  pValue->SetInteger(GetXFANodeList()->GetLength());
-}
diff --git a/fxjs/cjx_nodelist.h b/fxjs/cjx_nodelist.h
deleted file mode 100644
index df87998..0000000
--- a/fxjs/cjx_nodelist.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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
-
-#ifndef FXJS_CJX_NODELIST_H_
-#define FXJS_CJX_NODELIST_H_
-
-#include "fxjs/cjx_object.h"
-#include "xfa/fxfa/fxfa_basic.h"
-
-class CFXJSE_Arguments;
-class CFXJSE_Value;
-class CXFA_NodeList;
-
-class CJX_NodeList : public CJX_Object {
- public:
-  explicit CJX_NodeList(CXFA_NodeList* list);
-  ~CJX_NodeList() override;
-
-  CXFA_NodeList* GetXFANodeList();
-
-  void Script_ListClass_Append(CFXJSE_Arguments* pArguments);
-  void Script_ListClass_Insert(CFXJSE_Arguments* pArguments);
-  void Script_ListClass_Remove(CFXJSE_Arguments* pArguments);
-  void Script_ListClass_Item(CFXJSE_Arguments* pArguments);
-
-  void Script_TreelistClass_NamedItem(CFXJSE_Arguments* pArguments);
-  void Script_ListClass_Length(CFXJSE_Value* pValue,
-                               bool bSetting,
-                               XFA_Attribute eAttribute);
-};
-
-#endif  // FXJS_CJX_NODELIST_H_
diff --git a/fxjs/cjx_object.cpp b/fxjs/cjx_object.cpp
index 49c147b..21eb3c8 100644
--- a/fxjs/cjx_object.cpp
+++ b/fxjs/cjx_object.cpp
@@ -6,13 +6,83 @@
 
 #include "fxjs/cjx_object.h"
 
+#include <map>
+#include <utility>
+
+#include "core/fxcrt/fx_extension.h"
+#include "core/fxcrt/xml/cfx_xmltext.h"
 #include "fxjs/cfxjse_value.h"
+#include "third_party/base/ptr_util.h"
+#include "xfa/fxfa/cxfa_ffnotify.h"
+#include "xfa/fxfa/cxfa_ffwidget.h"
 #include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_measurement.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
 #include "xfa/fxfa/parser/cxfa_object.h"
 
+namespace {
+
+void XFA_DeleteWideString(void* pData) {
+  delete static_cast<WideString*>(pData);
+}
+
+void XFA_CopyWideString(void*& pData) {
+  if (!pData)
+    return;
+  pData = new WideString(*reinterpret_cast<WideString*>(pData));
+}
+
+XFA_MAPDATABLOCKCALLBACKINFO deleteWideStringCallBack = {XFA_DeleteWideString,
+                                                         XFA_CopyWideString};
+
+enum XFA_KEYTYPE {
+  XFA_KEYTYPE_Custom,
+  XFA_KEYTYPE_Element,
+};
+
+void* GetMapKey_Custom(const WideStringView& wsKey) {
+  uint32_t dwKey = FX_HashCode_GetW(wsKey, false);
+  return (void*)(uintptr_t)((dwKey << 1) | XFA_KEYTYPE_Custom);
+}
+
+void* GetMapKey_Element(XFA_Element eType, XFA_Attribute eAttribute) {
+  return (void*)(uintptr_t)((static_cast<uint32_t>(eType) << 16) |
+                            (static_cast<uint32_t>(eAttribute) << 8) |
+                            XFA_KEYTYPE_Element);
+}
+
+void XFA_DefaultFreeData(void* pData) {}
+
+XFA_MAPDATABLOCKCALLBACKINFO gs_XFADefaultFreeData = {XFA_DefaultFreeData,
+                                                      nullptr};
+
+}  // namespace
+
+struct XFA_MAPDATABLOCK {
+  uint8_t* GetData() const { return (uint8_t*)this + sizeof(XFA_MAPDATABLOCK); }
+
+  XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo;
+  int32_t iBytes;
+};
+
+struct XFA_MAPMODULEDATA {
+  XFA_MAPMODULEDATA() {}
+  ~XFA_MAPMODULEDATA() {}
+
+  std::map<void*, void*> m_ValueMap;
+  std::map<void*, XFA_MAPDATABLOCK*> m_BufferMap;
+};
+
 CJX_Object::CJX_Object(CXFA_Object* obj) : object_(obj) {}
 
-CJX_Object::~CJX_Object() {}
+CJX_Object::~CJX_Object() {
+  ClearMapModuleBuffer();
+}
+
+void CJX_Object::DefineMethods(const CJX_MethodSpec method_specs[]) {
+  for (size_t i = 0; method_specs[i].pMethodCall != nullptr; ++i)
+    method_specs_[method_specs[i].pName] = method_specs[i].pMethodCall;
+}
 
 CXFA_Document* CJX_Object::GetDocument() const {
   return object_->GetDocument();
@@ -29,6 +99,17 @@
       FX_UTF8Encode(GetXFAObject()->GetClassName()).AsStringView());
 }
 
+bool CJX_Object::HasMethod(const WideString& func) const {
+  return pdfium::ContainsKey(method_specs_, func.UTF8Encode());
+}
+
+void CJX_Object::RunMethod(const WideString& func, CFXJSE_Arguments* args) {
+  auto it = method_specs_.find(func.UTF8Encode());
+  if (it == method_specs_.end())
+    return;
+  it->second(this, args);
+}
+
 void CJX_Object::ThrowInvalidPropertyException() const {
   ThrowException(L"Invalid property set operation.");
 }
@@ -56,3 +137,666 @@
   ASSERT(!wsMessage.IsEmpty());
   FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView());
 }
+
+bool CJX_Object::HasAttribute(XFA_Attribute eAttr) {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  return HasMapModuleKey(pKey);
+}
+
+bool CJX_Object::SetAttribute(XFA_Attribute eAttr,
+                              const WideStringView& wsValue,
+                              bool bNotify) {
+  switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) {
+    case XFA_AttributeType::Enum: {
+      pdfium::Optional<XFA_AttributeEnum> item =
+          CXFA_Node::NameToAttributeEnum(wsValue);
+      return SetEnum(
+          eAttr,
+          item ? *item : *(ToNode(GetXFAObject())->GetDefaultEnum(eAttr)),
+          bNotify);
+    }
+    case XFA_AttributeType::CData:
+      return SetCData(eAttr, WideString(wsValue), bNotify, false);
+    case XFA_AttributeType::Boolean:
+      return SetBoolean(eAttr, wsValue != L"0", bNotify);
+    case XFA_AttributeType::Integer:
+      return SetInteger(eAttr,
+                        FXSYS_round(FXSYS_wcstof(wsValue.unterminated_c_str(),
+                                                 wsValue.GetLength(), nullptr)),
+                        bNotify);
+    case XFA_AttributeType::Measure:
+      return SetMeasure(eAttr, CXFA_Measurement(wsValue), bNotify);
+    default:
+      break;
+  }
+  return false;
+}
+
+void CJX_Object::SetMapModuleString(void* pKey, const WideStringView& wsValue) {
+  SetMapModuleBuffer(pKey, (void*)wsValue.unterminated_c_str(),
+                     wsValue.GetLength() * sizeof(wchar_t), nullptr);
+}
+
+bool CJX_Object::SetAttribute(const WideStringView& wsAttr,
+                              const WideStringView& wsValue,
+                              bool bNotify) {
+  XFA_Attribute attr = CXFA_Node::NameToAttribute(wsValue);
+  if (attr != XFA_Attribute::Unknown)
+    return SetAttribute(attr, wsValue, bNotify);
+
+  void* pKey = GetMapKey_Custom(wsAttr);
+  SetMapModuleString(pKey, wsValue);
+  return true;
+}
+
+WideString CJX_Object::GetAttribute(const WideStringView& attr) {
+  return TryAttribute(attr, true).value_or(WideString());
+}
+
+WideString CJX_Object::GetAttribute(XFA_Attribute attr) {
+  return TryAttribute(attr, true).value_or(WideString());
+}
+
+pdfium::Optional<WideString> CJX_Object::TryAttribute(XFA_Attribute eAttr,
+                                                      bool bUseDefault) {
+  switch (ToNode(GetXFAObject())->GetAttributeType(eAttr)) {
+    case XFA_AttributeType::Enum: {
+      pdfium::Optional<XFA_AttributeEnum> value = TryEnum(eAttr, bUseDefault);
+      if (!value)
+        return {};
+
+      return {CXFA_Node::AttributeEnumToName(*value)};
+    }
+    case XFA_AttributeType::CData:
+      return TryCData(eAttr, bUseDefault);
+
+    case XFA_AttributeType::Boolean: {
+      pdfium::Optional<bool> value = TryBoolean(eAttr, bUseDefault);
+      if (!value)
+        return {};
+      return {*value ? L"1" : L"0"};
+    }
+    case XFA_AttributeType::Integer: {
+      pdfium::Optional<int32_t> iValue = TryInteger(eAttr, bUseDefault);
+      if (!iValue)
+        return {};
+      return {WideString::Format(L"%d", *iValue)};
+    }
+    case XFA_AttributeType::Measure: {
+      pdfium::Optional<CXFA_Measurement> value = TryMeasure(eAttr, bUseDefault);
+      if (!value)
+        return {};
+
+      return {value->ToString()};
+    }
+    default:
+      break;
+  }
+  return {};
+}
+
+pdfium::Optional<WideString> CJX_Object::TryAttribute(
+    const WideStringView& wsAttr,
+    bool bUseDefault) {
+  XFA_Attribute attr = CXFA_Node::NameToAttribute(wsAttr);
+  if (attr != XFA_Attribute::Unknown)
+    return TryAttribute(attr, bUseDefault);
+
+  void* pKey = GetMapKey_Custom(wsAttr);
+  WideStringView wsValueC;
+  if (!GetMapModuleString(pKey, wsValueC))
+    return {};
+
+  return {WideString(wsValueC)};
+}
+
+void CJX_Object::RemoveAttribute(const WideStringView& wsAttr) {
+  void* pKey = GetMapKey_Custom(wsAttr);
+  if (pKey)
+    RemoveMapModuleKey(pKey);
+}
+
+pdfium::Optional<bool> CJX_Object::TryBoolean(XFA_Attribute eAttr,
+                                              bool bUseDefault) {
+  void* pValue = nullptr;
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  if (GetMapModuleValue(pKey, pValue))
+    return {!!pValue};
+  if (!bUseDefault)
+    return {};
+
+  return ToNode(GetXFAObject())->GetDefaultBoolean(eAttr);
+}
+
+bool CJX_Object::SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify) {
+  CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Boolean,
+                                  (void*)(uintptr_t)bValue, bNotify);
+  if (elem)
+    elem->SetString(CXFA_Node::AttributeToName(eAttr), bValue ? L"1" : L"0");
+  return true;
+}
+
+bool CJX_Object::GetBoolean(XFA_Attribute eAttr) {
+  return TryBoolean(eAttr, true).value_or(false);
+}
+
+bool CJX_Object::SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify) {
+  CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Integer,
+                                  (void*)(uintptr_t)iValue, bNotify);
+  if (elem) {
+    elem->SetString(CXFA_Node::AttributeToName(eAttr),
+                    WideString::Format(L"%d", iValue));
+  }
+  return true;
+}
+
+int32_t CJX_Object::GetInteger(XFA_Attribute eAttr) {
+  return TryInteger(eAttr, true).value_or(0);
+}
+
+pdfium::Optional<int32_t> CJX_Object::TryInteger(XFA_Attribute eAttr,
+                                                 bool bUseDefault) {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  void* pValue = nullptr;
+  if (GetMapModuleValue(pKey, pValue))
+    return {static_cast<int32_t>(reinterpret_cast<uintptr_t>(pValue))};
+  if (!bUseDefault)
+    return {};
+
+  return ToNode(GetXFAObject())->GetDefaultInteger(eAttr);
+}
+
+pdfium::Optional<XFA_AttributeEnum> CJX_Object::TryEnum(XFA_Attribute eAttr,
+                                                        bool bUseDefault) {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  void* pValue = nullptr;
+  if (GetMapModuleValue(pKey, pValue)) {
+    return {
+        static_cast<XFA_AttributeEnum>(reinterpret_cast<uintptr_t>(pValue))};
+  }
+  if (!bUseDefault)
+    return {};
+
+  return ToNode(GetXFAObject())->GetDefaultEnum(eAttr);
+}
+
+bool CJX_Object::SetEnum(XFA_Attribute eAttr,
+                         XFA_AttributeEnum eValue,
+                         bool bNotify) {
+  CFX_XMLElement* elem = SetValue(eAttr, XFA_AttributeType::Enum,
+                                  (void*)(uintptr_t)eValue, bNotify);
+  if (elem) {
+    elem->SetString(CXFA_Node::AttributeToName(eAttr),
+                    CXFA_Node::AttributeEnumToName(eValue));
+  }
+  return true;
+}
+
+XFA_AttributeEnum CJX_Object::GetEnum(XFA_Attribute eAttr) {
+  return TryEnum(eAttr, true).value_or(XFA_AttributeEnum::Unknown);
+}
+
+bool CJX_Object::SetMeasure(XFA_Attribute eAttr,
+                            CXFA_Measurement mValue,
+                            bool bNotify) {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  OnChanging(eAttr, bNotify);
+  SetMapModuleBuffer(pKey, &mValue, sizeof(CXFA_Measurement), nullptr);
+  OnChanged(eAttr, bNotify, false);
+  return true;
+}
+
+pdfium::Optional<CXFA_Measurement> CJX_Object::TryMeasure(
+    XFA_Attribute eAttr,
+    bool bUseDefault) const {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  void* pValue;
+  int32_t iBytes;
+  if (GetMapModuleBuffer(pKey, pValue, iBytes, true) &&
+      iBytes == sizeof(CXFA_Measurement)) {
+    return {*reinterpret_cast<CXFA_Measurement*>(pValue)};
+  }
+  if (!bUseDefault)
+    return {};
+
+  return ToNode(GetXFAObject())->GetDefaultMeasurement(eAttr);
+}
+
+CXFA_Measurement CJX_Object::GetMeasure(XFA_Attribute eAttr) const {
+  return TryMeasure(eAttr, true).value_or(CXFA_Measurement());
+}
+
+WideString CJX_Object::GetCData(XFA_Attribute eAttr) {
+  return TryCData(eAttr, true).value_or(WideString());
+}
+
+bool CJX_Object::SetCData(XFA_Attribute eAttr,
+                          const WideString& wsValue,
+                          bool bNotify,
+                          bool bScriptModify) {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  OnChanging(eAttr, bNotify);
+  if (eAttr == XFA_Attribute::Value) {
+    WideString* pClone = new WideString(wsValue);
+    SetUserData(pKey, pClone, &deleteWideStringCallBack);
+  } else {
+    SetMapModuleString(pKey, wsValue.AsStringView());
+    if (eAttr == XFA_Attribute::Name)
+      ToNode(GetXFAObject())->UpdateNameHash();
+  }
+  OnChanged(eAttr, bNotify, bScriptModify);
+
+  if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode() ||
+      eAttr == XFA_Attribute::QualifiedName ||
+      eAttr == XFA_Attribute::BindingNode) {
+    return true;
+  }
+
+  if (eAttr == XFA_Attribute::Name &&
+      (GetXFAObject()->GetElementType() == XFA_Element::DataValue ||
+       GetXFAObject()->GetElementType() == XFA_Element::DataGroup)) {
+    return true;
+  }
+
+  auto* elem =
+      static_cast<CFX_XMLElement*>(ToNode(GetXFAObject())->GetXMLMappingNode());
+  if (eAttr == XFA_Attribute::Value) {
+    FX_XMLNODETYPE eXMLType = elem->GetType();
+    switch (eXMLType) {
+      case FX_XMLNODE_Element:
+        if (ToNode(GetXFAObject())->IsAttributeInXML()) {
+          elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
+                          wsValue);
+        } else {
+          bool bDeleteChildren = true;
+          if (ToNode(GetXFAObject())->GetPacketType() ==
+              XFA_PacketType::Datasets) {
+            for (CXFA_Node* pChildDataNode =
+                     ToNode(GetXFAObject())
+                         ->GetNodeItem(XFA_NODEITEM_FirstChild);
+                 pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem(
+                                     XFA_NODEITEM_NextSibling)) {
+              if (!pChildDataNode->GetBindItems()->empty()) {
+                bDeleteChildren = false;
+                break;
+              }
+            }
+          }
+          if (bDeleteChildren)
+            elem->DeleteChildren();
+
+          elem->SetTextData(wsValue);
+        }
+        break;
+      case FX_XMLNODE_Text:
+        static_cast<CFX_XMLText*>(ToNode(GetXFAObject())->GetXMLMappingNode())
+            ->SetText(wsValue);
+        break;
+      default:
+        NOTREACHED();
+    }
+    return true;
+  }
+  ASSERT(elem->GetType() == FX_XMLNODE_Element);
+
+  WideString wsAttrName = CXFA_Node::AttributeToName(eAttr);
+  if (eAttr == XFA_Attribute::ContentType)
+    wsAttrName = L"xfa:" + wsAttrName;
+
+  elem->SetString(wsAttrName, wsValue);
+  return true;
+}
+
+void CJX_Object::SetAttributeValue(const WideString& wsValue,
+                                   const WideString& wsXMLValue,
+                                   bool bNotify,
+                                   bool bScriptModify) {
+  void* pKey =
+      GetMapKey_Element(GetXFAObject()->GetElementType(), XFA_Attribute::Value);
+  OnChanging(XFA_Attribute::Value, bNotify);
+  WideString* pClone = new WideString(wsValue);
+  SetUserData(pKey, pClone, &deleteWideStringCallBack);
+  OnChanged(XFA_Attribute::Value, bNotify, bScriptModify);
+  if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode())
+    return;
+
+  auto* elem =
+      static_cast<CFX_XMLElement*>(ToNode(GetXFAObject())->GetXMLMappingNode());
+  FX_XMLNODETYPE eXMLType = elem->GetType();
+  switch (eXMLType) {
+    case FX_XMLNODE_Element:
+      if (ToNode(GetXFAObject())->IsAttributeInXML()) {
+        elem->SetString(WideString(GetCData(XFA_Attribute::QualifiedName)),
+                        wsXMLValue);
+      } else {
+        bool bDeleteChildren = true;
+        if (ToNode(GetXFAObject())->GetPacketType() ==
+            XFA_PacketType::Datasets) {
+          for (CXFA_Node* pChildDataNode =
+                   ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_FirstChild);
+               pChildDataNode; pChildDataNode = pChildDataNode->GetNodeItem(
+                                   XFA_NODEITEM_NextSibling)) {
+            if (!pChildDataNode->GetBindItems()->empty()) {
+              bDeleteChildren = false;
+              break;
+            }
+          }
+        }
+        if (bDeleteChildren)
+          elem->DeleteChildren();
+
+        elem->SetTextData(wsXMLValue);
+      }
+      break;
+    case FX_XMLNODE_Text:
+      static_cast<CFX_XMLText*>(ToNode(GetXFAObject())->GetXMLMappingNode())
+          ->SetText(wsXMLValue);
+      break;
+    default:
+      ASSERT(0);
+  }
+}
+
+pdfium::Optional<WideString> CJX_Object::TryCData(XFA_Attribute eAttr,
+                                                  bool bUseDefault) {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  if (eAttr == XFA_Attribute::Value) {
+    void* pData;
+    int32_t iBytes = 0;
+    WideString* pStr = nullptr;
+    if (GetMapModuleBuffer(pKey, pData, iBytes, true) &&
+        iBytes == sizeof(void*)) {
+      memcpy(&pData, pData, iBytes);
+      pStr = reinterpret_cast<WideString*>(pData);
+    }
+    if (pStr)
+      return {*pStr};
+  } else {
+    WideStringView wsValueC;
+    if (GetMapModuleString(pKey, wsValueC))
+      return {WideString(wsValueC)};
+  }
+  if (!bUseDefault)
+    return {};
+
+  return ToNode(GetXFAObject())->GetDefaultCData(eAttr);
+}
+
+CFX_XMLElement* CJX_Object::SetValue(XFA_Attribute eAttr,
+                                     XFA_AttributeType eType,
+                                     void* pValue,
+                                     bool bNotify) {
+  void* pKey = GetMapKey_Element(GetXFAObject()->GetElementType(), eAttr);
+  OnChanging(eAttr, bNotify);
+  SetMapModuleValue(pKey, pValue);
+  OnChanged(eAttr, bNotify, false);
+  if (!ToNode(GetXFAObject())->IsNeedSavingXMLNode())
+    return nullptr;
+
+  auto* elem =
+      static_cast<CFX_XMLElement*>(ToNode(GetXFAObject())->GetXMLMappingNode());
+  ASSERT(elem->GetType() == FX_XMLNODE_Element);
+
+  return elem;
+}
+
+bool CJX_Object::SetUserData(void* pKey,
+                             void* pData,
+                             XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
+  SetMapModuleBuffer(pKey, &pData, sizeof(void*),
+                     pCallbackInfo ? pCallbackInfo : &gs_XFADefaultFreeData);
+  return true;
+}
+
+XFA_MAPMODULEDATA* CJX_Object::CreateMapModuleData() {
+  if (!map_module_data_)
+    map_module_data_ = pdfium::MakeUnique<XFA_MAPMODULEDATA>();
+  return map_module_data_.get();
+}
+
+XFA_MAPMODULEDATA* CJX_Object::GetMapModuleData() const {
+  return map_module_data_.get();
+}
+
+void CJX_Object::SetMapModuleValue(void* pKey, void* pValue) {
+  CreateMapModuleData()->m_ValueMap[pKey] = pValue;
+}
+
+bool CJX_Object::GetMapModuleValue(void* pKey, void*& pValue) {
+  for (CXFA_Node* pNode = ToNode(GetXFAObject()); pNode;
+       pNode = pNode->GetTemplateNode()) {
+    XFA_MAPMODULEDATA* pModule = pNode->JSNode()->GetMapModuleData();
+    if (pModule) {
+      auto it = pModule->m_ValueMap.find(pKey);
+      if (it != pModule->m_ValueMap.end()) {
+        pValue = it->second;
+        return true;
+      }
+    }
+    if (pNode->GetPacketType() == XFA_PacketType::Datasets)
+      break;
+  }
+  return false;
+}
+
+bool CJX_Object::GetMapModuleString(void* pKey, WideStringView& wsValue) {
+  void* pValue;
+  int32_t iBytes;
+  if (!GetMapModuleBuffer(pKey, pValue, iBytes, true))
+    return false;
+
+  // Defensive measure: no out-of-bounds pointers even if zero length.
+  int32_t iChars = iBytes / sizeof(wchar_t);
+  wsValue = WideStringView(iChars ? (const wchar_t*)pValue : nullptr, iChars);
+  return true;
+}
+
+void CJX_Object::SetMapModuleBuffer(
+    void* pKey,
+    void* pValue,
+    int32_t iBytes,
+    XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo) {
+  XFA_MAPDATABLOCK*& pBuffer = CreateMapModuleData()->m_BufferMap[pKey];
+  if (!pBuffer) {
+    pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
+        FX_Alloc(uint8_t, sizeof(XFA_MAPDATABLOCK) + iBytes));
+  } else if (pBuffer->iBytes != iBytes) {
+    if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
+      pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
+
+    pBuffer = reinterpret_cast<XFA_MAPDATABLOCK*>(
+        FX_Realloc(uint8_t, pBuffer, sizeof(XFA_MAPDATABLOCK) + iBytes));
+  } else if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree) {
+    pBuffer->pCallbackInfo->pFree(
+        *reinterpret_cast<void**>(pBuffer->GetData()));
+  }
+  if (!pBuffer)
+    return;
+
+  pBuffer->pCallbackInfo = pCallbackInfo;
+  pBuffer->iBytes = iBytes;
+  memcpy(pBuffer->GetData(), pValue, iBytes);
+}
+
+bool CJX_Object::GetMapModuleBuffer(void* pKey,
+                                    void*& pValue,
+                                    int32_t& iBytes,
+                                    bool bProtoAlso) const {
+  XFA_MAPDATABLOCK* pBuffer = nullptr;
+  for (const CXFA_Node* pNode = ToNode(GetXFAObject()); pNode;
+       pNode = pNode->GetTemplateNode()) {
+    XFA_MAPMODULEDATA* pModule = pNode->JSNode()->GetMapModuleData();
+    if (pModule) {
+      auto it = pModule->m_BufferMap.find(pKey);
+      if (it != pModule->m_BufferMap.end()) {
+        pBuffer = it->second;
+        break;
+      }
+    }
+    if (!bProtoAlso || pNode->GetPacketType() == XFA_PacketType::Datasets)
+      break;
+  }
+  if (!pBuffer)
+    return false;
+
+  pValue = pBuffer->GetData();
+  iBytes = pBuffer->iBytes;
+  return true;
+}
+
+bool CJX_Object::HasMapModuleKey(void* pKey) {
+  XFA_MAPMODULEDATA* pModule = GetMapModuleData();
+  return pModule && (pdfium::ContainsKey(pModule->m_ValueMap, pKey) ||
+                     pdfium::ContainsKey(pModule->m_BufferMap, pKey));
+}
+
+void CJX_Object::ClearMapModuleBuffer() {
+  XFA_MAPMODULEDATA* pModule = GetMapModuleData();
+  if (!pModule)
+    return;
+
+  for (auto& pair : pModule->m_BufferMap) {
+    XFA_MAPDATABLOCK* pBuffer = pair.second;
+    if (pBuffer) {
+      if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
+        pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
+
+      FX_Free(pBuffer);
+    }
+  }
+  pModule->m_BufferMap.clear();
+  pModule->m_ValueMap.clear();
+}
+
+void CJX_Object::RemoveMapModuleKey(void* pKey) {
+  ASSERT(pKey);
+
+  XFA_MAPMODULEDATA* pModule = GetMapModuleData();
+  if (!pModule)
+    return;
+
+  auto it = pModule->m_BufferMap.find(pKey);
+  if (it != pModule->m_BufferMap.end()) {
+    XFA_MAPDATABLOCK* pBuffer = it->second;
+    if (pBuffer) {
+      if (pBuffer->pCallbackInfo && pBuffer->pCallbackInfo->pFree)
+        pBuffer->pCallbackInfo->pFree(*(void**)pBuffer->GetData());
+
+      FX_Free(pBuffer);
+    }
+    pModule->m_BufferMap.erase(it);
+  }
+  pModule->m_ValueMap.erase(pKey);
+  return;
+}
+
+void CJX_Object::MergeAllData(CXFA_Object* pDstModule) {
+  XFA_MAPMODULEDATA* pDstModuleData =
+      ToNode(pDstModule)->JSNode()->CreateMapModuleData();
+  XFA_MAPMODULEDATA* pSrcModuleData = GetMapModuleData();
+  if (!pSrcModuleData)
+    return;
+
+  for (const auto& pair : pSrcModuleData->m_ValueMap)
+    pDstModuleData->m_ValueMap[pair.first] = pair.second;
+
+  for (const auto& pair : pSrcModuleData->m_BufferMap) {
+    XFA_MAPDATABLOCK* pSrcBuffer = pair.second;
+    XFA_MAPDATABLOCK*& pDstBuffer = pDstModuleData->m_BufferMap[pair.first];
+    if (pSrcBuffer->pCallbackInfo && pSrcBuffer->pCallbackInfo->pFree &&
+        !pSrcBuffer->pCallbackInfo->pCopy) {
+      if (pDstBuffer) {
+        pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
+        pDstModuleData->m_BufferMap.erase(pair.first);
+      }
+      continue;
+    }
+    if (!pDstBuffer) {
+      pDstBuffer = (XFA_MAPDATABLOCK*)FX_Alloc(
+          uint8_t, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
+    } else if (pDstBuffer->iBytes != pSrcBuffer->iBytes) {
+      if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
+        pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
+      }
+      pDstBuffer = (XFA_MAPDATABLOCK*)FX_Realloc(
+          uint8_t, pDstBuffer, sizeof(XFA_MAPDATABLOCK) + pSrcBuffer->iBytes);
+    } else if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pFree) {
+      pDstBuffer->pCallbackInfo->pFree(*(void**)pDstBuffer->GetData());
+    }
+    if (!pDstBuffer)
+      continue;
+
+    pDstBuffer->pCallbackInfo = pSrcBuffer->pCallbackInfo;
+    pDstBuffer->iBytes = pSrcBuffer->iBytes;
+    memcpy(pDstBuffer->GetData(), pSrcBuffer->GetData(), pSrcBuffer->iBytes);
+    if (pDstBuffer->pCallbackInfo && pDstBuffer->pCallbackInfo->pCopy) {
+      pDstBuffer->pCallbackInfo->pCopy(*(void**)pDstBuffer->GetData());
+    }
+  }
+}
+
+void CJX_Object::MoveBufferMapData(CXFA_Object* pDstModule) {
+  if (!pDstModule)
+    return;
+
+  bool bNeedMove = true;
+  if (pDstModule->GetElementType() != GetXFAObject()->GetElementType())
+    bNeedMove = false;
+
+  if (bNeedMove)
+    ToNode(pDstModule)->JSNode()->SetCalcData(ReleaseCalcData());
+  if (!pDstModule->IsNodeV())
+    return;
+
+  WideString wsValue = ToNode(pDstModule)->JSNode()->GetContent(false);
+  WideString wsFormatValue(wsValue);
+  CXFA_WidgetData* pWidgetData = ToNode(pDstModule)->GetContainerWidgetData();
+  if (pWidgetData)
+    wsFormatValue = pWidgetData->GetFormatDataValue(wsValue);
+
+  ToNode(pDstModule)
+      ->JSNode()
+      ->SetContent(wsValue, wsFormatValue, true, true, true);
+}
+
+void CJX_Object::MoveBufferMapData(CXFA_Object* pSrcModule,
+                                   CXFA_Object* pDstModule) {
+  if (!pSrcModule || !pDstModule)
+    return;
+
+  CXFA_Node* pSrcChild =
+      ToNode(pSrcModule)->GetNodeItem(XFA_NODEITEM_FirstChild);
+  CXFA_Node* pDstChild =
+      ToNode(pDstModule)->GetNodeItem(XFA_NODEITEM_FirstChild);
+  while (pSrcChild && pDstChild) {
+    MoveBufferMapData(pSrcChild, pDstChild);
+
+    pSrcChild = pSrcChild->GetNodeItem(XFA_NODEITEM_NextSibling);
+    pDstChild = pDstChild->GetNodeItem(XFA_NODEITEM_NextSibling);
+  }
+  ToNode(pSrcModule)->JSNode()->MoveBufferMapData(pDstModule);
+}
+
+void CJX_Object::OnChanging(XFA_Attribute eAttr, bool bNotify) {
+  if (!bNotify || !ToNode(GetXFAObject())->IsInitialized())
+    return;
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (pNotify)
+    pNotify->OnValueChanging(ToNode(GetXFAObject()), eAttr);
+}
+
+void CJX_Object::OnChanged(XFA_Attribute eAttr,
+                           bool bNotify,
+                           bool bScriptModify) {
+  if (bNotify && ToNode(GetXFAObject())->IsInitialized())
+    ToNode(GetXFAObject())->SendAttributeChangeMessage(eAttr, bScriptModify);
+}
+
+void CJX_Object::SetCalcData(std::unique_ptr<CXFA_CalcData> data) {
+  calc_data_ = std::move(data);
+}
+
+std::unique_ptr<CXFA_CalcData> CJX_Object::ReleaseCalcData() {
+  return std::move(calc_data_);
+}
diff --git a/fxjs/cjx_object.h b/fxjs/cjx_object.h
index d05956c..c945c1e 100644
--- a/fxjs/cjx_object.h
+++ b/fxjs/cjx_object.h
@@ -7,13 +7,34 @@
 #ifndef FXJS_CJX_OBJECT_H_
 #define FXJS_CJX_OBJECT_H_
 
+#include <map>
+#include <memory>
+
 #include "core/fxcrt/unowned_ptr.h"
 #include "core/fxcrt/widestring.h"
+#include "core/fxcrt/xml/cfx_xmlelement.h"
 #include "xfa/fxfa/fxfa_basic.h"
 
+typedef void (*CJX_MethodCall)(CJX_Object* obj, CFXJSE_Arguments* args);
+
+struct CJX_MethodSpec {
+  const char* pName;
+  CJX_MethodCall pMethodCall;
+};
+
+typedef void (*PD_CALLBACK_FREEDATA)(void* pData);
+typedef void (*PD_CALLBACK_DUPLICATEDATA)(void*& pData);
+
+struct XFA_MAPDATABLOCKCALLBACKINFO {
+  PD_CALLBACK_FREEDATA pFree;
+  PD_CALLBACK_DUPLICATEDATA pCopy;
+};
+
 class CFXJSE_Value;
-class CXFA_Object;
+class CXFA_CalcData;
 class CXFA_Document;
+class CXFA_Object;
+struct XFA_MAPMODULEDATA;
 
 class CJX_Object {
  public:
@@ -24,22 +45,114 @@
 
   CXFA_Document* GetDocument() const;
 
+  bool HasMethod(const WideString& func) const;
+  void RunMethod(const WideString& func, CFXJSE_Arguments* args);
+
+  bool HasAttribute(XFA_Attribute eAttr);
+  bool SetAttribute(XFA_Attribute eAttr,
+                    const WideStringView& wsValue,
+                    bool bNotify);
+  bool SetAttribute(const WideStringView& wsAttr,
+                    const WideStringView& wsValue,
+                    bool bNotify);
+  void RemoveAttribute(const WideStringView& wsAttr);
+  WideString GetAttribute(const WideStringView& attr);
+  WideString GetAttribute(XFA_Attribute attr);
+  pdfium::Optional<WideString> TryAttribute(const WideStringView& wsAttr,
+                                            bool bUseDefault);
+  pdfium::Optional<WideString> TryAttribute(XFA_Attribute eAttr,
+                                            bool bUseDefault);
+
+  void SetAttributeValue(const WideString& wsValue,
+                         const WideString& wsXMLValue,
+                         bool bNotify,
+                         bool bScriptModify);
+
+  pdfium::Optional<int32_t> TryInteger(XFA_Attribute eAttr, bool bUseDefault);
+  bool SetInteger(XFA_Attribute eAttr, int32_t iValue, bool bNotify);
+  int32_t GetInteger(XFA_Attribute eAttr);
+
+  pdfium::Optional<WideString> TryCData(XFA_Attribute eAttr, bool bUseDefault);
+  bool SetCData(XFA_Attribute eAttr,
+                const WideString& wsValue,
+                bool bNotify,
+                bool bScriptModify);
+  WideString GetCData(XFA_Attribute eAttr);
+
+  pdfium::Optional<XFA_AttributeEnum> TryEnum(XFA_Attribute eAttr,
+                                              bool bUseDefault);
+  bool SetEnum(XFA_Attribute eAttr, XFA_AttributeEnum eValue, bool bNotify);
+  XFA_AttributeEnum GetEnum(XFA_Attribute eAttr);
+
+  pdfium::Optional<bool> TryBoolean(XFA_Attribute eAttr, bool bUseDefault);
+  bool SetBoolean(XFA_Attribute eAttr, bool bValue, bool bNotify);
+  bool GetBoolean(XFA_Attribute eAttr);
+
+  pdfium::Optional<CXFA_Measurement> TryMeasure(XFA_Attribute eAttr,
+                                                bool bUseDefault) const;
+  bool SetMeasure(XFA_Attribute eAttr, CXFA_Measurement mValue, bool bNotify);
+  CXFA_Measurement GetMeasure(XFA_Attribute eAttr) const;
+
   void Script_ObjectClass_ClassName(CFXJSE_Value* pValue,
                                     bool bSetting,
                                     XFA_Attribute eAttribute);
 
+  void MergeAllData(CXFA_Object* pDstModule);
+
+  void SetCalcData(std::unique_ptr<CXFA_CalcData> data);
+  CXFA_CalcData* GetCalcData() const { return calc_data_.get(); }
+  std::unique_ptr<CXFA_CalcData> ReleaseCalcData();
+
   void ThrowInvalidPropertyException() const;
   void ThrowArgumentMismatchException() const;
   void ThrowIndexOutOfBoundsException() const;
   void ThrowParamCountMismatchException(const WideString& method) const;
 
  protected:
-  explicit CJX_Object(CXFA_Object* object);
+  explicit CJX_Object(CXFA_Object* obj);
 
+  void DefineMethods(const CJX_MethodSpec method_specs[]);
+
+  void MoveBufferMapData(CXFA_Object* pSrcModule, CXFA_Object* pDstModule);
+  void SetMapModuleString(void* pKey, const WideStringView& wsValue);
   void ThrowException(const wchar_t* str, ...) const;
 
  private:
+  void OnChanged(XFA_Attribute eAttr, bool bNotify, bool bScriptModify);
+  void OnChanging(XFA_Attribute eAttr, bool bNotify);
+  bool SetUserData(void* pKey,
+                   void* pData,
+                   XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo);
+
+  // Returns a pointer to the XML node that needs to be updated with the new
+  // attribute value. |nullptr| if no update is needed.
+  CFX_XMLElement* SetValue(XFA_Attribute eAttr,
+                           XFA_AttributeType eType,
+                           void* pValue,
+                           bool bNotify);
+
+  XFA_MAPMODULEDATA* CreateMapModuleData();
+  XFA_MAPMODULEDATA* GetMapModuleData() const;
+  void SetMapModuleValue(void* pKey, void* pValue);
+  bool GetMapModuleValue(void* pKey, void*& pValue);
+  bool GetMapModuleString(void* pKey, WideStringView& wsValue);
+  void SetMapModuleBuffer(void* pKey,
+                          void* pValue,
+                          int32_t iBytes,
+                          XFA_MAPDATABLOCKCALLBACKINFO* pCallbackInfo);
+  bool GetMapModuleBuffer(void* pKey,
+                          void*& pValue,
+                          int32_t& iBytes,
+                          bool bProtoAlso) const;
+  bool HasMapModuleKey(void* pKey);
+  void ClearMapModuleBuffer();
+  void RemoveMapModuleKey(void* pKey);
+  void MoveBufferMapData(CXFA_Object* pDstModule);
+
   UnownedPtr<CXFA_Object> object_;
+  std::unique_ptr<XFA_MAPMODULEDATA> map_module_data_;
+  std::unique_ptr<CXFA_CalcData> calc_data_;
+  std::map<ByteString, CJX_MethodCall> method_specs_;
 };
 
 #endif  // FXJS_CJX_OBJECT_H_
diff --git a/fxjs/cjx_signaturepseudomodel.cpp b/fxjs/cjx_signaturepseudomodel.cpp
index 76cf989..b50e5dc 100644
--- a/fxjs/cjx_signaturepseudomodel.cpp
+++ b/fxjs/cjx_signaturepseudomodel.cpp
@@ -10,13 +10,22 @@
 #include "fxjs/cfxjse_value.h"
 #include "xfa/fxfa/parser/cscript_signaturepseudomodel.h"
 
+const CJX_MethodSpec CJX_SignaturePseudoModel::MethodSpecs[] = {
+    {"verify", verifySignature_static},
+    {"sign", sign_static},
+    {"enumerate", enumerate_static},
+    {"clear", clear_static},
+    {"", nullptr}};
+
 CJX_SignaturePseudoModel::CJX_SignaturePseudoModel(
     CScript_SignaturePseudoModel* model)
-    : CJX_Object(model) {}
+    : CJX_Object(model) {
+  DefineMethods(MethodSpecs);
+}
 
 CJX_SignaturePseudoModel::~CJX_SignaturePseudoModel() {}
 
-void CJX_SignaturePseudoModel::Verify(CFXJSE_Arguments* pArguments) {
+void CJX_SignaturePseudoModel::verifySignature(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 4) {
     ThrowParamCountMismatchException(L"verify");
@@ -28,7 +37,7 @@
     pValue->SetInteger(0);
 }
 
-void CJX_SignaturePseudoModel::Sign(CFXJSE_Arguments* pArguments) {
+void CJX_SignaturePseudoModel::sign(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 3 || iLength > 7) {
     ThrowParamCountMismatchException(L"sign");
@@ -40,7 +49,7 @@
     pValue->SetBoolean(false);
 }
 
-void CJX_SignaturePseudoModel::Enumerate(CFXJSE_Arguments* pArguments) {
+void CJX_SignaturePseudoModel::enumerate(CFXJSE_Arguments* pArguments) {
   if (pArguments->GetLength() != 0) {
     ThrowParamCountMismatchException(L"enumerate");
     return;
@@ -48,7 +57,7 @@
   return;
 }
 
-void CJX_SignaturePseudoModel::Clear(CFXJSE_Arguments* pArguments) {
+void CJX_SignaturePseudoModel::clear(CFXJSE_Arguments* pArguments) {
   int32_t iLength = pArguments->GetLength();
   if (iLength < 1 || iLength > 2) {
     ThrowParamCountMismatchException(L"clear");
diff --git a/fxjs/cjx_signaturepseudomodel.h b/fxjs/cjx_signaturepseudomodel.h
index e0e1f09..d0508dd 100644
--- a/fxjs/cjx_signaturepseudomodel.h
+++ b/fxjs/cjx_signaturepseudomodel.h
@@ -7,10 +7,9 @@
 #ifndef FXJS_CJX_SIGNATUREPSEUDOMODEL_H_
 #define FXJS_CJX_SIGNATUREPSEUDOMODEL_H_
 
+#include "fxjs/CJX_Define.h"
 #include "fxjs/cjx_object.h"
 
-class CFXJSE_Arguments;
-class CFXJSE_Value;
 class CScript_SignaturePseudoModel;
 
 class CJX_SignaturePseudoModel : public CJX_Object {
@@ -18,10 +17,13 @@
   explicit CJX_SignaturePseudoModel(CScript_SignaturePseudoModel* model);
   ~CJX_SignaturePseudoModel() override;
 
-  void Verify(CFXJSE_Arguments* pArguments);
-  void Sign(CFXJSE_Arguments* pArguments);
-  void Enumerate(CFXJSE_Arguments* pArguments);
-  void Clear(CFXJSE_Arguments* pArguments);
+  JS_METHOD(verifySignature /*verify*/, CJX_SignaturePseudoModel);
+  JS_METHOD(sign, CJX_SignaturePseudoModel);
+  JS_METHOD(enumerate, CJX_SignaturePseudoModel);
+  JS_METHOD(clear, CJX_SignaturePseudoModel);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
 };
 
 #endif  // FXJS_CJX_SIGNATUREPSEUDOMODEL_H_
diff --git a/fxjs/xfa/cjx_container.cpp b/fxjs/xfa/cjx_container.cpp
new file mode 100644
index 0000000..517fb86
--- /dev/null
+++ b/fxjs/xfa/cjx_container.cpp
@@ -0,0 +1,33 @@
+// 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_container.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_arraynodelist.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_field.h"
+
+const CJX_MethodSpec CJX_Container::MethodSpecs[] = {
+    {"getDelta", getDelta_static},
+    {"getDeltas", getDeltas_static},
+    {"", nullptr}};
+
+CJX_Container::CJX_Container(CXFA_Node* node) : CJX_Node(node) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Container::~CJX_Container() {}
+
+void CJX_Container::getDelta(CFXJSE_Arguments* pArguments) {}
+
+void CJX_Container::getDeltas(CFXJSE_Arguments* pArguments) {
+  CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(GetDocument());
+  pArguments->GetReturnValue()->SetObject(
+      pFormNodes, GetDocument()->GetScriptContext()->GetJseNormalClass());
+}
diff --git a/fxjs/xfa/cjx_container.h b/fxjs/xfa/cjx_container.h
new file mode 100644
index 0000000..41d11cf
--- /dev/null
+++ b/fxjs/xfa/cjx_container.h
@@ -0,0 +1,27 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_CONTAINER_H_
+#define FXJS_XFA_CJX_CONTAINER_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_Node;
+
+class CJX_Container : public CJX_Node {
+ public:
+  explicit CJX_Container(CXFA_Node* node);
+  ~CJX_Container() override;
+
+  JS_METHOD(getDelta, CJX_Container);
+  JS_METHOD(getDeltas, CJX_Container);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_CONTAINER_H_
diff --git a/fxjs/xfa/cjx_content.cpp b/fxjs/xfa/cjx_content.cpp
new file mode 100644
index 0000000..87ddf63
--- /dev/null
+++ b/fxjs/xfa/cjx_content.cpp
@@ -0,0 +1,15 @@
+// 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_content.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_object.h"
+
+CJX_Content::CJX_Content(CXFA_Object* obj) : CJX_Object(obj) {}
+
+CJX_Content::~CJX_Content() {}
diff --git a/fxjs/xfa/cjx_content.h b/fxjs/xfa/cjx_content.h
new file mode 100644
index 0000000..cd2e71a
--- /dev/null
+++ b/fxjs/xfa/cjx_content.h
@@ -0,0 +1,21 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_CONTENT_H_
+#define FXJS_XFA_CJX_CONTENT_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_object.h"
+
+class CXFA_Content;
+
+class CJX_Content : public CJX_Object {
+ public:
+  explicit CJX_Content(CXFA_Object* obj);
+  ~CJX_Content() override;
+};
+
+#endif  // FXJS_XFA_CJX_CONTENT_H_
diff --git a/fxjs/xfa/cjx_delta.cpp b/fxjs/xfa/cjx_delta.cpp
new file mode 100644
index 0000000..b661ae9
--- /dev/null
+++ b/fxjs/xfa/cjx_delta.cpp
@@ -0,0 +1,25 @@
+// 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_delta.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_delta.h"
+
+const CJX_MethodSpec CJX_Delta::MethodSpecs[] = {{"restore", restore_static},
+                                                 {"", nullptr}};
+
+CJX_Delta::CJX_Delta(CXFA_Delta* delta) : CJX_Object(delta) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Delta::~CJX_Delta() {}
+
+void CJX_Delta::restore(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"restore");
+}
diff --git a/fxjs/xfa/cjx_delta.h b/fxjs/xfa/cjx_delta.h
new file mode 100644
index 0000000..d9a2c62
--- /dev/null
+++ b/fxjs/xfa/cjx_delta.h
@@ -0,0 +1,26 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_DELTA_H_
+#define FXJS_XFA_CJX_DELTA_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_object.h"
+
+class CXFA_Delta;
+
+class CJX_Delta : public CJX_Object {
+ public:
+  explicit CJX_Delta(CXFA_Delta* delta);
+  ~CJX_Delta() override;
+
+  JS_METHOD(restore, CJX_Delta);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_DELTA_H_
diff --git a/fxjs/xfa/cjx_desc.cpp b/fxjs/xfa/cjx_desc.cpp
new file mode 100644
index 0000000..4efd1dd
--- /dev/null
+++ b/fxjs/xfa/cjx_desc.cpp
@@ -0,0 +1,29 @@
+// 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_desc.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_desc.h"
+
+const CJX_MethodSpec CJX_Desc::MethodSpecs[] = {{"metadata", metadata_static},
+                                                {"", nullptr}};
+
+CJX_Desc::CJX_Desc(CXFA_Desc* desc) : CJX_Node(desc) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Desc::~CJX_Desc() {}
+
+void CJX_Desc::metadata(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 0 && argc != 1) {
+    ThrowParamCountMismatchException(L"metadata");
+    return;
+  }
+  pArguments->GetReturnValue()->SetString("");
+}
diff --git a/fxjs/xfa/cjx_desc.h b/fxjs/xfa/cjx_desc.h
new file mode 100644
index 0000000..602633d
--- /dev/null
+++ b/fxjs/xfa/cjx_desc.h
@@ -0,0 +1,26 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_DESC_H_
+#define FXJS_XFA_CJX_DESC_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_Desc;
+
+class CJX_Desc : public CJX_Node {
+ public:
+  explicit CJX_Desc(CXFA_Desc* desc);
+  ~CJX_Desc() override;
+
+  JS_METHOD(metadata, CJX_Desc);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_DESC_H_
diff --git a/fxjs/xfa/cjx_exclgroup.cpp b/fxjs/xfa/cjx_exclgroup.cpp
new file mode 100644
index 0000000..c84ec94
--- /dev/null
+++ b/fxjs/xfa/cjx_exclgroup.cpp
@@ -0,0 +1,118 @@
+// 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_exclgroup.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/cxfa_eventparam.h"
+#include "xfa/fxfa/cxfa_ffnotify.h"
+#include "xfa/fxfa/fxfa.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_exclgroup.h"
+#include "xfa/fxfa/parser/cxfa_widgetdata.h"
+
+const CJX_MethodSpec CJX_ExclGroup::MethodSpecs[] = {
+    {"execCalculate", execCalculate_static},
+    {"execEvent", execEvent_static},
+    {"execInitialize", execInitialize_static},
+    {"execValidate", execValidate_static},
+    {"selectedMember", selectedMember_static},
+    {"", nullptr}};
+
+CJX_ExclGroup::CJX_ExclGroup(CXFA_ExclGroup* group) : CJX_Node(group) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_ExclGroup::~CJX_ExclGroup() {}
+
+void CJX_ExclGroup::execEvent(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"execEvent");
+    return;
+  }
+
+  ByteString eventString = pArguments->GetUTF8String(0);
+  execSingleEventByName(
+      WideString::FromUTF8(eventString.AsStringView()).AsStringView(),
+      XFA_Element::ExclGroup);
+}
+
+void CJX_ExclGroup::execInitialize(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execInitialize");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize);
+}
+
+void CJX_ExclGroup::execCalculate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execCalculate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
+}
+
+void CJX_ExclGroup::execValidate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execValidate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify) {
+    pArguments->GetReturnValue()->SetBoolean(false);
+    return;
+  }
+
+  int32_t iRet =
+      pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
+  pArguments->GetReturnValue()->SetBoolean(
+      (iRet == XFA_EVENTERROR_Error) ? false : true);
+}
+
+void CJX_ExclGroup::selectedMember(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc < 0 || argc > 1) {
+    ThrowParamCountMismatchException(L"selectedMember");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+
+  CXFA_Node* pReturnNode = nullptr;
+  if (argc == 0) {
+    pReturnNode = pWidgetData->GetSelectedMember();
+  } else {
+    ByteString szName;
+    szName = pArguments->GetUTF8String(0);
+    pReturnNode = pWidgetData->SetSelectedMember(
+        WideString::FromUTF8(szName.AsStringView()).AsStringView(), true);
+  }
+  if (!pReturnNode) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+
+  pArguments->GetReturnValue()->Assign(
+      GetDocument()->GetScriptContext()->GetJSValueFromMap(pReturnNode));
+}
diff --git a/fxjs/xfa/cjx_exclgroup.h b/fxjs/xfa/cjx_exclgroup.h
new file mode 100644
index 0000000..2ef280e
--- /dev/null
+++ b/fxjs/xfa/cjx_exclgroup.h
@@ -0,0 +1,30 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_EXCLGROUP_H_
+#define FXJS_XFA_CJX_EXCLGROUP_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_ExclGroup;
+
+class CJX_ExclGroup : public CJX_Node {
+ public:
+  explicit CJX_ExclGroup(CXFA_ExclGroup* group);
+  ~CJX_ExclGroup() override;
+
+  JS_METHOD(execCalculate, CJX_ExclGroup);
+  JS_METHOD(execEvent, CJX_ExclGroup);
+  JS_METHOD(execInitialize, CJX_ExclGroup);
+  JS_METHOD(execValidate, CJX_ExclGroup);
+  JS_METHOD(selectedMember, CJX_ExclGroup);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_EXCLGROUP_H_
diff --git a/fxjs/xfa/cjx_field.cpp b/fxjs/xfa/cjx_field.cpp
new file mode 100644
index 0000000..f0dbc78
--- /dev/null
+++ b/fxjs/xfa/cjx_field.cpp
@@ -0,0 +1,263 @@
+// 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_field.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/cxfa_eventparam.h"
+#include "xfa/fxfa/cxfa_ffnotify.h"
+#include "xfa/fxfa/fxfa.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_field.h"
+#include "xfa/fxfa/parser/cxfa_widgetdata.h"
+
+const CJX_MethodSpec CJX_Field::MethodSpecs[] = {
+    {"addItem", addItem_static},
+    {"boundItem", boundItem_static},
+    {"clearItems", clearItems_static},
+    {"deleteItem", deleteItem_static},
+    {"execCalculate", execCalculate_static},
+    {"execEvent", execEvent_static},
+    {"execInitialize", execInitialize_static},
+    {"execValidate", execValidate_static},
+    {"getDisplayItem", getDisplayItem_static},
+    {"getItemState", getItemState_static},
+    {"getSaveItem", getSaveItem_static},
+    {"setItemState", setItemState_static},
+    {"", nullptr}};
+
+CJX_Field::CJX_Field(CXFA_Field* field) : CJX_Container(field) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Field::~CJX_Field() {}
+
+void CJX_Field::clearItems(CFXJSE_Arguments* pArguments) {
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData)
+    return;
+
+  pWidgetData->DeleteItem(-1, true, false);
+}
+
+void CJX_Field::execEvent(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"execEvent");
+    return;
+  }
+
+  ByteString eventString = pArguments->GetUTF8String(0);
+  int32_t iRet = execSingleEventByName(
+      WideString::FromUTF8(eventString.AsStringView()).AsStringView(),
+      XFA_Element::Field);
+  if (eventString != "validate")
+    return;
+
+  pArguments->GetReturnValue()->SetBoolean(
+      (iRet == XFA_EVENTERROR_Error) ? false : true);
+}
+
+void CJX_Field::execInitialize(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execInitialize");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize, false,
+                                false);
+}
+
+void CJX_Field::deleteItem(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength != 1) {
+    ThrowParamCountMismatchException(L"deleteItem");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData)
+    return;
+
+  int32_t iIndex = pArguments->GetInt32(0);
+  bool bValue = pWidgetData->DeleteItem(iIndex, true, true);
+  CFXJSE_Value* pValue = pArguments->GetReturnValue();
+  if (pValue)
+    pValue->SetBoolean(bValue);
+}
+
+void CJX_Field::getSaveItem(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength != 1) {
+    ThrowParamCountMismatchException(L"getSaveItem");
+    return;
+  }
+
+  int32_t iIndex = pArguments->GetInt32(0);
+  if (iIndex < 0) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+
+  pdfium::Optional<WideString> value =
+      pWidgetData->GetChoiceListItem(iIndex, true);
+  if (!value) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+  pArguments->GetReturnValue()->SetString(value->UTF8Encode().AsStringView());
+}
+
+void CJX_Field::boundItem(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength != 1) {
+    ThrowParamCountMismatchException(L"boundItem");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData)
+    return;
+
+  ByteString bsValue = pArguments->GetUTF8String(0);
+  WideString wsValue = WideString::FromUTF8(bsValue.AsStringView());
+  WideString wsBoundValue = pWidgetData->GetItemValue(wsValue.AsStringView());
+  CFXJSE_Value* pValue = pArguments->GetReturnValue();
+  if (pValue)
+    pValue->SetString(wsBoundValue.UTF8Encode().AsStringView());
+}
+
+void CJX_Field::getItemState(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength != 1) {
+    ThrowParamCountMismatchException(L"getItemState");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData)
+    return;
+
+  CFXJSE_Value* pValue = pArguments->GetReturnValue();
+  if (pValue)
+    pValue->SetBoolean(pWidgetData->GetItemState(pArguments->GetInt32(0)));
+}
+
+void CJX_Field::execCalculate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execCalculate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate, false,
+                                false);
+}
+
+void CJX_Field::getDisplayItem(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength != 1) {
+    ThrowParamCountMismatchException(L"getDisplayItem");
+    return;
+  }
+
+  int32_t iIndex = pArguments->GetInt32(0);
+  if (iIndex < 0) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+
+  pdfium::Optional<WideString> value =
+      pWidgetData->GetChoiceListItem(iIndex, false);
+  if (!value) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+  pArguments->GetReturnValue()->SetString(value->UTF8Encode().AsStringView());
+}
+
+void CJX_Field::setItemState(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 2) {
+    ThrowParamCountMismatchException(L"setItemState");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData)
+    return;
+
+  int32_t iIndex = pArguments->GetInt32(0);
+  if (pArguments->GetInt32(1) != 0) {
+    pWidgetData->SetItemState(iIndex, true, true, true, true);
+    return;
+  }
+
+  if (pWidgetData->GetItemState(iIndex))
+    pWidgetData->SetItemState(iIndex, false, true, true, true);
+}
+
+void CJX_Field::addItem(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength < 1 || iLength > 2) {
+    ThrowParamCountMismatchException(L"addItem");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData)
+    return;
+
+  WideString wsLabel;
+  if (iLength >= 1) {
+    ByteString bsLabel = pArguments->GetUTF8String(0);
+    wsLabel = WideString::FromUTF8(bsLabel.AsStringView());
+  }
+
+  WideString wsValue;
+  if (iLength >= 2) {
+    ByteString bsValue = pArguments->GetUTF8String(1);
+    wsValue = WideString::FromUTF8(bsValue.AsStringView());
+  }
+
+  pWidgetData->InsertItem(wsLabel, wsValue, true);
+}
+
+void CJX_Field::execValidate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execValidate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify) {
+    pArguments->GetReturnValue()->SetBoolean(false);
+    return;
+  }
+
+  int32_t iRet = pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate,
+                                               false, false);
+  pArguments->GetReturnValue()->SetBoolean(
+      (iRet == XFA_EVENTERROR_Error) ? false : true);
+}
diff --git a/fxjs/xfa/cjx_field.h b/fxjs/xfa/cjx_field.h
new file mode 100644
index 0000000..524a6af
--- /dev/null
+++ b/fxjs/xfa/cjx_field.h
@@ -0,0 +1,37 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_FIELD_H_
+#define FXJS_XFA_CJX_FIELD_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/xfa/cjx_container.h"
+
+class CXFA_Field;
+
+class CJX_Field : public CJX_Container {
+ public:
+  explicit CJX_Field(CXFA_Field* field);
+  ~CJX_Field() override;
+
+  JS_METHOD(addItem, CJX_Field);
+  JS_METHOD(boundItem, CJX_Field);
+  JS_METHOD(clearItems, CJX_Field);
+  JS_METHOD(deleteItem, CJX_Field);
+  JS_METHOD(execCalculate, CJX_Field);
+  JS_METHOD(execEvent, CJX_Field);
+  JS_METHOD(execInitialize, CJX_Field);
+  JS_METHOD(execValidate, CJX_Field);
+  JS_METHOD(getDisplayItem, CJX_Field);
+  JS_METHOD(getItemState, CJX_Field);
+  JS_METHOD(getSaveItem, CJX_Field);
+  JS_METHOD(setItemState, CJX_Field);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_FIELD_H_
diff --git a/fxjs/xfa/cjx_form.cpp b/fxjs/xfa/cjx_form.cpp
new file mode 100644
index 0000000..106910c
--- /dev/null
+++ b/fxjs/xfa/cjx_form.cpp
@@ -0,0 +1,128 @@
+// 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_form.h"
+
+#include <vector>
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/cxfa_eventparam.h"
+#include "xfa/fxfa/cxfa_ffnotify.h"
+#include "xfa/fxfa/parser/cxfa_arraynodelist.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_form.h"
+
+const CJX_MethodSpec CJX_Form::MethodSpecs[] = {
+    {"execCalculate", execCalculate_static},
+    {"execInitialize", execInitialize_static},
+    {"execValidate", execValidate_static},
+    {"formNodes", formNodes_static},
+    {"recalculate", recalculate_static},
+    {"remerge", remerge_static},
+    {"", nullptr}};
+
+CJX_Form::CJX_Form(CXFA_Form* form) : CJX_Model(form) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Form::~CJX_Form() {}
+
+void CJX_Form::formNodes(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"formNodes");
+    return;
+  }
+
+  CXFA_Node* pDataNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
+  if (!pDataNode) {
+    ThrowArgumentMismatchException();
+    return;
+  }
+
+  std::vector<CXFA_Node*> formItems;
+  CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(GetDocument());
+  pFormNodes->SetArrayNodeList(formItems);
+  pArguments->GetReturnValue()->SetObject(
+      pFormNodes, GetDocument()->GetScriptContext()->GetJseNormalClass());
+}
+
+void CJX_Form::remerge(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"remerge");
+    return;
+  }
+
+  GetDocument()->DoDataRemerge(true);
+}
+
+void CJX_Form::execInitialize(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execInitialize");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize);
+}
+
+void CJX_Form::recalculate(CFXJSE_Arguments* pArguments) {
+  CXFA_EventParam* pEventParam =
+      GetDocument()->GetScriptContext()->GetEventParam();
+  if (pEventParam->m_eType == XFA_EVENT_Calculate ||
+      pEventParam->m_eType == XFA_EVENT_InitCalculate) {
+    return;
+  }
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"recalculate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+  if (pArguments->GetInt32(0) != 0)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Ready, true);
+}
+
+void CJX_Form::execCalculate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execCalculate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
+}
+
+void CJX_Form::execValidate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execValidate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify) {
+    pArguments->GetReturnValue()->SetBoolean(false);
+    return;
+  }
+
+  int32_t iRet =
+      pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
+  pArguments->GetReturnValue()->SetBoolean(
+      (iRet == XFA_EVENTERROR_Error) ? false : true);
+}
diff --git a/fxjs/xfa/cjx_form.h b/fxjs/xfa/cjx_form.h
new file mode 100644
index 0000000..e4d64da
--- /dev/null
+++ b/fxjs/xfa/cjx_form.h
@@ -0,0 +1,31 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_FORM_H_
+#define FXJS_XFA_CJX_FORM_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/xfa/cjx_model.h"
+
+class CXFA_Form;
+
+class CJX_Form : public CJX_Model {
+ public:
+  explicit CJX_Form(CXFA_Form* form);
+  ~CJX_Form() override;
+
+  JS_METHOD(execCalculate, CJX_Form);
+  JS_METHOD(execInitialize, CJX_Form);
+  JS_METHOD(execValidate, CJX_Form);
+  JS_METHOD(formNodes, CJX_Form);
+  JS_METHOD(recalculate, CJX_Form);
+  JS_METHOD(remerge, CJX_Form);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_FORM_H_
diff --git a/fxjs/xfa/cjx_instancemanager.cpp b/fxjs/xfa/cjx_instancemanager.cpp
new file mode 100644
index 0000000..da8422e
--- /dev/null
+++ b/fxjs/xfa/cjx_instancemanager.cpp
@@ -0,0 +1,180 @@
+// 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_instancemanager.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/cxfa_ffnotify.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_instancemanager.h"
+#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
+#include "xfa/fxfa/parser/cxfa_occurdata.h"
+
+const CJX_MethodSpec CJX_InstanceManager::MethodSpecs[] = {
+    {"addInstance", addInstance_static},
+    {"insertInstance", insertInstance_static},
+    {"moveInstance", moveInstance_static},
+    {"removeInstance", removeInstance_static},
+    {"setInstances", setInstances_static},
+    {"", nullptr}};
+
+CJX_InstanceManager::CJX_InstanceManager(CXFA_InstanceManager* mgr)
+    : CJX_Node(mgr) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_InstanceManager::~CJX_InstanceManager() {}
+
+void CJX_InstanceManager::moveInstance(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 2) {
+    pArguments->GetReturnValue()->SetUndefined();
+    return;
+  }
+
+  int32_t iFrom = pArguments->GetInt32(0);
+  int32_t iTo = pArguments->GetInt32(1);
+  InstanceManager_MoveInstance(iTo, iFrom);
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  CXFA_Node* pToInstance = GetXFANode()->GetItem(iTo);
+  if (pToInstance && pToInstance->GetElementType() == XFA_Element::Subform)
+    pNotify->RunSubformIndexChange(pToInstance);
+
+  CXFA_Node* pFromInstance = GetXFANode()->GetItem(iFrom);
+  if (pFromInstance &&
+      pFromInstance->GetElementType() == XFA_Element::Subform) {
+    pNotify->RunSubformIndexChange(pFromInstance);
+  }
+}
+
+void CJX_InstanceManager::removeInstance(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    pArguments->GetReturnValue()->SetUndefined();
+    return;
+  }
+
+  int32_t iIndex = pArguments->GetInt32(0);
+  int32_t iCount = GetXFANode()->GetCount();
+  if (iIndex < 0 || iIndex >= iCount) {
+    ThrowIndexOutOfBoundsException();
+    return;
+  }
+
+  int32_t iMin = CXFA_OccurData(GetXFANode()->GetOccurNode()).GetMin();
+  if (iCount - 1 < iMin) {
+    ThrowTooManyOccurancesException(L"min");
+    return;
+  }
+
+  CXFA_Node* pRemoveInstance = GetXFANode()->GetItem(iIndex);
+  GetXFANode()->RemoveItem(pRemoveInstance, true);
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (pNotify) {
+    for (int32_t i = iIndex; i < iCount - 1; i++) {
+      CXFA_Node* pSubformInstance = GetXFANode()->GetItem(i);
+      if (pSubformInstance &&
+          pSubformInstance->GetElementType() == XFA_Element::Subform) {
+        pNotify->RunSubformIndexChange(pSubformInstance);
+      }
+    }
+  }
+  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
+  if (!pLayoutPro)
+    return;
+
+  pLayoutPro->AddChangedContainer(
+      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
+}
+
+void CJX_InstanceManager::setInstances(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    pArguments->GetReturnValue()->SetUndefined();
+    return;
+  }
+
+  int32_t iDesired = pArguments->GetInt32(0);
+  InstanceManager_SetInstances(iDesired);
+}
+
+void CJX_InstanceManager::addInstance(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 0 && argc != 1) {
+    ThrowParamCountMismatchException(L"addInstance");
+    return;
+  }
+
+  bool fFlags = true;
+  if (argc == 1)
+    fFlags = pArguments->GetInt32(0) == 0 ? false : true;
+
+  int32_t iCount = GetXFANode()->GetCount();
+  int32_t iMax = CXFA_OccurData(GetXFANode()->GetOccurNode()).GetMax();
+  if (iMax >= 0 && iCount >= iMax) {
+    ThrowTooManyOccurancesException(L"max");
+    return;
+  }
+
+  CXFA_Node* pNewInstance = GetXFANode()->CreateInstance(fFlags);
+  GetXFANode()->InsertItem(pNewInstance, iCount, iCount, false);
+  pArguments->GetReturnValue()->Assign(
+      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance));
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->RunNodeInitialize(pNewInstance);
+  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
+  if (!pLayoutPro)
+    return;
+
+  pLayoutPro->AddChangedContainer(
+      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
+}
+
+void CJX_InstanceManager::insertInstance(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 1 && argc != 2) {
+    ThrowParamCountMismatchException(L"insertInstance");
+    return;
+  }
+
+  int32_t iIndex = pArguments->GetInt32(0);
+  bool bBind = false;
+  if (argc == 2)
+    bBind = pArguments->GetInt32(1) == 0 ? false : true;
+
+  int32_t iCount = GetXFANode()->GetCount();
+  if (iIndex < 0 || iIndex > iCount) {
+    ThrowIndexOutOfBoundsException();
+    return;
+  }
+
+  int32_t iMax = CXFA_OccurData(GetXFANode()->GetOccurNode()).GetMax();
+  if (iMax >= 0 && iCount >= iMax) {
+    ThrowTooManyOccurancesException(L"max");
+    return;
+  }
+
+  CXFA_Node* pNewInstance = GetXFANode()->CreateInstance(bBind);
+  GetXFANode()->InsertItem(pNewInstance, iIndex, iCount, true);
+  pArguments->GetReturnValue()->Assign(
+      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance));
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->RunNodeInitialize(pNewInstance);
+  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
+  if (!pLayoutPro)
+    return;
+
+  pLayoutPro->AddChangedContainer(
+      ToNode(GetDocument()->GetXFAObject(XFA_HASHCODE_Form)));
+}
diff --git a/fxjs/xfa/cjx_instancemanager.h b/fxjs/xfa/cjx_instancemanager.h
new file mode 100644
index 0000000..a312366
--- /dev/null
+++ b/fxjs/xfa/cjx_instancemanager.h
@@ -0,0 +1,30 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_INSTANCEMANAGER_H_
+#define FXJS_XFA_CJX_INSTANCEMANAGER_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_InstanceManager;
+
+class CJX_InstanceManager : public CJX_Node {
+ public:
+  explicit CJX_InstanceManager(CXFA_InstanceManager* mgr);
+  ~CJX_InstanceManager() override;
+
+  JS_METHOD(addInstance, CJX_InstanceManager);
+  JS_METHOD(insertInstance, CJX_InstanceManager);
+  JS_METHOD(moveInstance, CJX_InstanceManager);
+  JS_METHOD(removeInstance, CJX_InstanceManager);
+  JS_METHOD(setInstances, CJX_InstanceManager);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_INSTANCEMANAGER_H_
diff --git a/fxjs/xfa/cjx_list.cpp b/fxjs/xfa/cjx_list.cpp
new file mode 100644
index 0000000..34cf9da
--- /dev/null
+++ b/fxjs/xfa/cjx_list.cpp
@@ -0,0 +1,103 @@
+// 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_list.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_list.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
+
+const CJX_MethodSpec CJX_List::MethodSpecs[] = {{"append", append_static},
+                                                {"insert", insert_static},
+                                                {"item", item_static},
+                                                {"remove", remove_static},
+                                                {"", nullptr}};
+
+CJX_List::CJX_List(CXFA_List* list) : CJX_Object(list) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_List::~CJX_List() {}
+
+CXFA_List* CJX_List::GetXFAList() {
+  return static_cast<CXFA_List*>(GetXFAObject());
+}
+
+void CJX_List::append(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 1) {
+    ThrowParamCountMismatchException(L"append");
+    return;
+  }
+
+  auto* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
+  if (!pNode) {
+    ThrowArgumentMismatchException();
+    return;
+  }
+  GetXFAList()->Append(pNode);
+}
+
+void CJX_List::insert(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 2) {
+    ThrowParamCountMismatchException(L"insert");
+    return;
+  }
+
+  auto* pNewNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
+  auto* pBeforeNode = static_cast<CXFA_Node*>(pArguments->GetObject(1));
+  if (!pNewNode) {
+    ThrowArgumentMismatchException();
+    return;
+  }
+  GetXFAList()->Insert(pNewNode, pBeforeNode);
+}
+
+void CJX_List::remove(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 1) {
+    ThrowParamCountMismatchException(L"remove");
+    return;
+  }
+
+  auto* pNode = static_cast<CXFA_Node*>(pArguments->GetObject(0));
+  if (!pNode) {
+    ThrowArgumentMismatchException();
+    return;
+  }
+  GetXFAList()->Remove(pNode);
+}
+
+void CJX_List::item(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 1) {
+    ThrowParamCountMismatchException(L"item");
+    return;
+  }
+
+  int32_t iIndex = pArguments->GetInt32(0);
+  if (iIndex < 0 || iIndex >= GetXFAList()->GetLength()) {
+    ThrowIndexOutOfBoundsException();
+    return;
+  }
+  pArguments->GetReturnValue()->Assign(
+      GetDocument()->GetScriptContext()->GetJSValueFromMap(
+          GetXFAList()->Item(iIndex)));
+}
+
+void CJX_List::length(CFXJSE_Value* pValue,
+                      bool bSetting,
+                      XFA_Attribute eAttribute) {
+  if (bSetting) {
+    ThrowInvalidPropertyException();
+    return;
+  }
+  pValue->SetInteger(GetXFAList()->GetLength());
+}
diff --git a/fxjs/xfa/cjx_list.h b/fxjs/xfa/cjx_list.h
new file mode 100644
index 0000000..b4a0025
--- /dev/null
+++ b/fxjs/xfa/cjx_list.h
@@ -0,0 +1,33 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_LIST_H_
+#define FXJS_XFA_CJX_LIST_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_object.h"
+
+class CXFA_List;
+
+class CJX_List : public CJX_Object {
+ public:
+  explicit CJX_List(CXFA_List* list);
+  ~CJX_List() override;
+
+  JS_METHOD(append, CJX_List);
+  JS_METHOD(insert, CJX_List);
+  JS_METHOD(item, CJX_List);
+  JS_METHOD(remove, CJX_List);
+
+  void length(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
+
+ private:
+  CXFA_List* GetXFAList();
+
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_LIST_H_
diff --git a/fxjs/xfa/cjx_manifest.cpp b/fxjs/xfa/cjx_manifest.cpp
new file mode 100644
index 0000000..066ba29
--- /dev/null
+++ b/fxjs/xfa/cjx_manifest.cpp
@@ -0,0 +1,35 @@
+// 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_manifest.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_manifest.h"
+
+const CJX_MethodSpec CJX_Manifest::MethodSpecs[] = {
+    {"evaluate", evaluate_static},
+    {"", nullptr}};
+
+CJX_Manifest::CJX_Manifest(CXFA_Manifest* manifest) : CJX_Node(manifest) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Manifest::~CJX_Manifest() {}
+
+void CJX_Manifest::evaluate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"evaluate");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData) {
+    pArguments->GetReturnValue()->SetBoolean(false);
+    return;
+  }
+  pArguments->GetReturnValue()->SetBoolean(true);
+}
diff --git a/fxjs/xfa/cjx_manifest.h b/fxjs/xfa/cjx_manifest.h
new file mode 100644
index 0000000..167ef46
--- /dev/null
+++ b/fxjs/xfa/cjx_manifest.h
@@ -0,0 +1,26 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_MANIFEST_H_
+#define FXJS_XFA_CJX_MANIFEST_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_Manifest;
+
+class CJX_Manifest : public CJX_Node {
+ public:
+  explicit CJX_Manifest(CXFA_Manifest* manifest);
+  ~CJX_Manifest() override;
+
+  JS_METHOD(evaluate, CJX_Manifest);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_MANIFEST_H_
diff --git a/fxjs/xfa/cjx_model.cpp b/fxjs/xfa/cjx_model.cpp
new file mode 100644
index 0000000..cd738b0
--- /dev/null
+++ b/fxjs/xfa/cjx_model.cpp
@@ -0,0 +1,94 @@
+// 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_model.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_delta.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+
+const CJX_MethodSpec CJX_Model::MethodSpecs[] = {
+    {"clearErrorList", clearErrorList_static},
+    {"createNode", createNode_static},
+    {"isCompatibleNS", isCompatibleNS_static},
+    {"", nullptr}};
+
+CJX_Model::CJX_Model(CXFA_Node* node) : CJX_Node(node) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Model::~CJX_Model() {}
+
+void CJX_Model::clearErrorList(CFXJSE_Arguments* pArguments) {}
+
+void CJX_Model::createNode(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc <= 0 || argc >= 4) {
+    ThrowParamCountMismatchException(L"createNode");
+    return;
+  }
+
+  WideString strName;
+  WideString strNameSpace;
+  if (argc > 1) {
+    ByteString bsName = pArguments->GetUTF8String(1);
+    strName = WideString::FromUTF8(bsName.AsStringView());
+    if (argc == 3) {
+      ByteString bsNameSpace = pArguments->GetUTF8String(2);
+      strNameSpace = WideString::FromUTF8(bsNameSpace.AsStringView());
+    }
+  }
+
+  ByteString bsTagName = pArguments->GetUTF8String(0);
+  WideString strTagName = WideString::FromUTF8(bsTagName.AsStringView());
+  XFA_Element eType = CXFA_Node::NameToElement(strTagName);
+  CXFA_Node* pNewNode = GetXFANode()->CreateSamePacketNode(eType);
+  if (!pNewNode) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+
+  if (strName.IsEmpty()) {
+    pArguments->GetReturnValue()->Assign(
+        GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewNode));
+    return;
+  }
+
+  if (!pNewNode->HasAttribute(XFA_Attribute::Name)) {
+    ThrowMissingPropertyException(strTagName, L"name");
+    return;
+  }
+
+  pNewNode->JSNode()->SetAttribute(XFA_Attribute::Name, strName.AsStringView(),
+                                   true);
+  if (pNewNode->GetPacketType() == XFA_PacketType::Datasets)
+    pNewNode->CreateXMLMappingNode();
+
+  pArguments->GetReturnValue()->Assign(
+      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewNode));
+}
+
+void CJX_Model::isCompatibleNS(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength < 1) {
+    ThrowParamCountMismatchException(L"isCompatibleNS");
+    return;
+  }
+
+  WideString wsNameSpace;
+  if (iLength >= 1) {
+    ByteString bsNameSpace = pArguments->GetUTF8String(0);
+    wsNameSpace = WideString::FromUTF8(bsNameSpace.AsStringView());
+  }
+
+  CFXJSE_Value* pValue = pArguments->GetReturnValue();
+  if (!pValue)
+    return;
+
+  pValue->SetBoolean(TryNamespace().value_or(WideString()) == wsNameSpace);
+}
diff --git a/fxjs/xfa/cjx_model.h b/fxjs/xfa/cjx_model.h
new file mode 100644
index 0000000..f4e6ac9
--- /dev/null
+++ b/fxjs/xfa/cjx_model.h
@@ -0,0 +1,28 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_MODEL_H_
+#define FXJS_XFA_CJX_MODEL_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_Node;
+
+class CJX_Model : public CJX_Node {
+ public:
+  explicit CJX_Model(CXFA_Node* obj);
+  ~CJX_Model() override;
+
+  JS_METHOD(clearErrorList, CJX_Model);
+  JS_METHOD(createNode, CJX_Model);
+  JS_METHOD(isCompatibleNS, CJX_Model);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_MODEL_H_
diff --git a/fxjs/xfa/cjx_packet.cpp b/fxjs/xfa/cjx_packet.cpp
new file mode 100644
index 0000000..b1424d2
--- /dev/null
+++ b/fxjs/xfa/cjx_packet.cpp
@@ -0,0 +1,75 @@
+// 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_packet.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_packet.h"
+
+const CJX_MethodSpec CJX_Packet::MethodSpecs[] = {
+    {"getAttribute", getAttribute_static},
+    {"removeAttribute", removeAttribute_static},
+    {"setAttribute", setAttribute_static},
+    {"", nullptr}};
+
+CJX_Packet::CJX_Packet(CXFA_Packet* packet) : CJX_Node(packet) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Packet::~CJX_Packet() {}
+
+void CJX_Packet::getAttribute(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"getAttribute");
+    return;
+  }
+
+  WideString wsAttributeValue;
+  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
+  if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
+    ByteString bsAttributeName = pArguments->GetUTF8String(0);
+    wsAttributeValue = static_cast<CFX_XMLElement*>(pXMLNode)->GetString(
+        WideString::FromUTF8(bsAttributeName.AsStringView()).c_str());
+  }
+
+  pArguments->GetReturnValue()->SetString(
+      wsAttributeValue.UTF8Encode().AsStringView());
+}
+
+void CJX_Packet::setAttribute(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 2) {
+    ThrowParamCountMismatchException(L"setAttribute");
+    return;
+  }
+
+  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
+  if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
+    ByteString bsValue = pArguments->GetUTF8String(0);
+    ByteString bsName = pArguments->GetUTF8String(1);
+    static_cast<CFX_XMLElement*>(pXMLNode)->SetString(
+        WideString::FromUTF8(bsName.AsStringView()),
+        WideString::FromUTF8(bsValue.AsStringView()));
+  }
+  pArguments->GetReturnValue()->SetNull();
+}
+
+void CJX_Packet::removeAttribute(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"removeAttribute");
+    return;
+  }
+
+  CFX_XMLNode* pXMLNode = GetXFANode()->GetXMLMappingNode();
+  if (pXMLNode && pXMLNode->GetType() == FX_XMLNODE_Element) {
+    ByteString bsName = pArguments->GetUTF8String(0);
+    WideString wsName = WideString::FromUTF8(bsName.AsStringView());
+    CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode);
+    if (pXMLElement->HasAttribute(wsName.c_str()))
+      pXMLElement->RemoveAttribute(wsName.c_str());
+  }
+  pArguments->GetReturnValue()->SetNull();
+}
diff --git a/fxjs/xfa/cjx_packet.h b/fxjs/xfa/cjx_packet.h
new file mode 100644
index 0000000..80520e2
--- /dev/null
+++ b/fxjs/xfa/cjx_packet.h
@@ -0,0 +1,28 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_PACKET_H_
+#define FXJS_XFA_CJX_PACKET_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_Packet;
+
+class CJX_Packet : public CJX_Node {
+ public:
+  explicit CJX_Packet(CXFA_Packet* packet);
+  ~CJX_Packet() override;
+
+  JS_METHOD(getAttribute, CJX_Packet);
+  JS_METHOD(removeAttribute, CJX_Packet);
+  JS_METHOD(setAttribute, CJX_Packet);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_PACKET_H_
diff --git a/fxjs/xfa/cjx_source.cpp b/fxjs/xfa/cjx_source.cpp
new file mode 100644
index 0000000..3197231
--- /dev/null
+++ b/fxjs/xfa/cjx_source.cpp
@@ -0,0 +1,122 @@
+// 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_source.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_source.h"
+
+const CJX_MethodSpec CJX_Source::MethodSpecs[] = {
+    {"addNew", addNew_static},
+    {"cancel", cancel_static},
+    {"cancelBatch", cancelBatch_static},
+    {"close", close_static},
+    {"delete", deleteItem_static},
+    {"first", first_static},
+    {"hasDataChanged", hasDataChanged_static},
+    {"isBOF", isBOF_static},
+    {"isEOF", isEOF_static},
+    {"last", last_static},
+    {"next", next_static},
+    {"open", open_static},
+    {"previous", previous_static},
+    {"requery", requery_static},
+    {"resync", resync_static},
+    {"update", update_static},
+    {"updateBatch", updateBatch_static},
+    {"", nullptr}};
+
+CJX_Source::CJX_Source(CXFA_Source* src) : CJX_Node(src) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Source::~CJX_Source() {}
+
+void CJX_Source::next(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"next");
+}
+
+void CJX_Source::cancelBatch(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"cancelBatch");
+}
+
+void CJX_Source::first(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"first");
+}
+
+void CJX_Source::updateBatch(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"updateBatch");
+}
+
+void CJX_Source::previous(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"previous");
+}
+
+void CJX_Source::isBOF(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"isBOF");
+}
+
+void CJX_Source::isEOF(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"isEOF");
+}
+
+void CJX_Source::cancel(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"cancel");
+}
+
+void CJX_Source::update(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"update");
+}
+
+void CJX_Source::open(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"open");
+}
+
+void CJX_Source::deleteItem(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"delete");
+}
+
+void CJX_Source::addNew(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"addNew");
+}
+
+void CJX_Source::requery(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"requery");
+}
+
+void CJX_Source::resync(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"resync");
+}
+
+void CJX_Source::close(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"close");
+}
+
+void CJX_Source::last(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"last");
+}
+
+void CJX_Source::hasDataChanged(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0)
+    ThrowParamCountMismatchException(L"hasDataChanged");
+}
diff --git a/fxjs/xfa/cjx_source.h b/fxjs/xfa/cjx_source.h
new file mode 100644
index 0000000..1502e0e
--- /dev/null
+++ b/fxjs/xfa/cjx_source.h
@@ -0,0 +1,42 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_SOURCE_H_
+#define FXJS_XFA_CJX_SOURCE_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_Source;
+
+class CJX_Source : public CJX_Node {
+ public:
+  explicit CJX_Source(CXFA_Source* src);
+  ~CJX_Source() override;
+
+  JS_METHOD(addNew, CJX_Source);
+  JS_METHOD(cancel, CJX_Source);
+  JS_METHOD(cancelBatch, CJX_Source);
+  JS_METHOD(close, CJX_Source);
+  JS_METHOD(deleteItem /*delete*/, CJX_Source);
+  JS_METHOD(first, CJX_Source);
+  JS_METHOD(hasDataChanged, CJX_Source);
+  JS_METHOD(isBOF, CJX_Source);
+  JS_METHOD(isEOF, CJX_Source);
+  JS_METHOD(last, CJX_Source);
+  JS_METHOD(next, CJX_Source);
+  JS_METHOD(open, CJX_Source);
+  JS_METHOD(previous, CJX_Source);
+  JS_METHOD(requery, CJX_Source);
+  JS_METHOD(resync, CJX_Source);
+  JS_METHOD(update, CJX_Source);
+  JS_METHOD(updateBatch, CJX_Source);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_SOURCE_H_
diff --git a/fxjs/xfa/cjx_subform.cpp b/fxjs/xfa/cjx_subform.cpp
new file mode 100644
index 0000000..32de182
--- /dev/null
+++ b/fxjs/xfa/cjx_subform.cpp
@@ -0,0 +1,84 @@
+// 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_subform.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/cxfa_eventparam.h"
+#include "xfa/fxfa/cxfa_ffnotify.h"
+#include "xfa/fxfa/fxfa.h"
+#include "xfa/fxfa/parser/cxfa_delta.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+
+const CJX_MethodSpec CJX_Subform::MethodSpecs[] = {
+    {"execCalculate", execCalculate_static},
+    {"execEvent", execEvent_static},
+    {"execInitialize", execInitialize_static},
+    {"execValidate", execValidate_static},
+    {"", nullptr}};
+
+CJX_Subform::CJX_Subform(CXFA_Node* node) : CJX_Container(node) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Subform::~CJX_Subform() {}
+
+void CJX_Subform::execEvent(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"execEvent");
+    return;
+  }
+
+  ByteString eventString = pArguments->GetUTF8String(0);
+  execSingleEventByName(
+      WideString::FromUTF8(eventString.AsStringView()).AsStringView(),
+      XFA_Element::Subform);
+}
+
+void CJX_Subform::execInitialize(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execInitialize");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Initialize);
+}
+
+void CJX_Subform::execCalculate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execCalculate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Calculate);
+}
+
+void CJX_Subform::execValidate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execValidate");
+    return;
+  }
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify) {
+    pArguments->GetReturnValue()->SetBoolean(false);
+    return;
+  }
+
+  int32_t iRet =
+      pNotify->ExecEventByDeepFirst(GetXFANode(), XFA_EVENT_Validate);
+  pArguments->GetReturnValue()->SetBoolean(
+      (iRet == XFA_EVENTERROR_Error) ? false : true);
+}
diff --git a/fxjs/xfa/cjx_subform.h b/fxjs/xfa/cjx_subform.h
new file mode 100644
index 0000000..a0227f0
--- /dev/null
+++ b/fxjs/xfa/cjx_subform.h
@@ -0,0 +1,29 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_SUBFORM_H_
+#define FXJS_XFA_CJX_SUBFORM_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/xfa/cjx_container.h"
+
+class CXFA_Delta;
+
+class CJX_Subform : public CJX_Container {
+ public:
+  explicit CJX_Subform(CXFA_Node* container);
+  ~CJX_Subform() override;
+
+  JS_METHOD(execCalculate, CJX_Subform);
+  JS_METHOD(execEvent, CJX_Subform);
+  JS_METHOD(execInitialize, CJX_Subform);
+  JS_METHOD(execValidate, CJX_Subform);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_SUBFORM_H_
diff --git a/fxjs/xfa/cjx_template.cpp b/fxjs/xfa/cjx_template.cpp
new file mode 100644
index 0000000..99db4ea
--- /dev/null
+++ b/fxjs/xfa/cjx_template.cpp
@@ -0,0 +1,87 @@
+// 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_template.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_template.h"
+
+const CJX_MethodSpec CJX_Template::MethodSpecs[] = {
+    {"execCalculate", execCalculate_static},
+    {"execInitialize", execInitialize_static},
+    {"execValidate", execValidate_static},
+    {"formNodes", formNodes_static},
+    {"recalculate", recalculate_static},
+    {"remerge", remerge_static},
+    {"", nullptr}};
+
+CJX_Template::CJX_Template(CXFA_Template* tmpl) : CJX_Model(tmpl) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Template::~CJX_Template() {}
+
+void CJX_Template::formNodes(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"formNodes");
+    return;
+  }
+  pArguments->GetReturnValue()->SetBoolean(true);
+}
+
+void CJX_Template::remerge(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"remerge");
+    return;
+  }
+  GetDocument()->DoDataRemerge(true);
+}
+
+void CJX_Template::execInitialize(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execInitialize");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData) {
+    pArguments->GetReturnValue()->SetBoolean(false);
+    return;
+  }
+  pArguments->GetReturnValue()->SetBoolean(true);
+}
+
+void CJX_Template::recalculate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 1) {
+    ThrowParamCountMismatchException(L"recalculate");
+    return;
+  }
+  pArguments->GetReturnValue()->SetBoolean(true);
+}
+
+void CJX_Template::execCalculate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execCalculate");
+    return;
+  }
+
+  CXFA_WidgetData* pWidgetData = GetXFANode()->GetWidgetData();
+  if (!pWidgetData) {
+    pArguments->GetReturnValue()->SetBoolean(false);
+    return;
+  }
+  pArguments->GetReturnValue()->SetBoolean(true);
+}
+
+void CJX_Template::execValidate(CFXJSE_Arguments* pArguments) {
+  if (pArguments->GetLength() != 0) {
+    ThrowParamCountMismatchException(L"execValidate");
+    return;
+  }
+  pArguments->GetReturnValue()->SetBoolean(!!GetXFANode()->GetWidgetData());
+}
diff --git a/fxjs/xfa/cjx_template.h b/fxjs/xfa/cjx_template.h
new file mode 100644
index 0000000..2c82788
--- /dev/null
+++ b/fxjs/xfa/cjx_template.h
@@ -0,0 +1,34 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_TEMPLATE_H_
+#define FXJS_XFA_CJX_TEMPLATE_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/xfa/cjx_model.h"
+
+class CXFA_Template;
+
+class CJX_Template : public CJX_Model {
+ public:
+  explicit CJX_Template(CXFA_Template* tmpl);
+  ~CJX_Template() override;
+
+  /* The docs list a |createNode| method on Template but that method already
+   * exists on Model, also the |createNode| docs say it exists on Model not
+   * on Template so I'm leaving |createNode| out of the template methods. */
+  JS_METHOD(execCalculate, CJX_Template);
+  JS_METHOD(execInitialize, CJX_Template);
+  JS_METHOD(execValidate, CJX_Template);
+  JS_METHOD(formNodes, CJX_Template);
+  JS_METHOD(recalculate, CJX_Template);
+  JS_METHOD(remerge, CJX_Template);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_TEMPLATE_H_
diff --git a/fxjs/xfa/cjx_textnode.cpp b/fxjs/xfa/cjx_textnode.cpp
new file mode 100644
index 0000000..4ebf3ce
--- /dev/null
+++ b/fxjs/xfa/cjx_textnode.cpp
@@ -0,0 +1,15 @@
+// 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_textnode.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
+
+CJX_TextNode::CJX_TextNode(CXFA_Node* node) : CJX_Node(node) {}
+
+CJX_TextNode::~CJX_TextNode() {}
diff --git a/fxjs/xfa/cjx_textnode.h b/fxjs/xfa/cjx_textnode.h
new file mode 100644
index 0000000..1fa84d8
--- /dev/null
+++ b/fxjs/xfa/cjx_textnode.h
@@ -0,0 +1,21 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_TEXTNODE_H_
+#define FXJS_XFA_CJX_TEXTNODE_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_Node;
+
+class CJX_TextNode : public CJX_Node {
+ public:
+  explicit CJX_TextNode(CXFA_Node* node);
+  ~CJX_TextNode() override;
+};
+
+#endif  // FXJS_XFA_CJX_TEXTNODE_H_
diff --git a/fxjs/xfa/cjx_tree.cpp b/fxjs/xfa/cjx_tree.cpp
new file mode 100644
index 0000000..69cbfa0
--- /dev/null
+++ b/fxjs/xfa/cjx_tree.cpp
@@ -0,0 +1,230 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "fxjs/xfa/cjx_tree.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "third_party/base/ptr_util.h"
+#include "xfa/fxfa/parser/cxfa_arraynodelist.h"
+#include "xfa/fxfa/parser/cxfa_attachnodelist.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxfa/parser/cxfa_object.h"
+#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
+
+const CJX_MethodSpec CJX_Tree::MethodSpecs[] = {
+    {"resolveNode", resolveNode_static},
+    {"resolveNodes", resolveNodes_static},
+    {"", nullptr}};
+
+CJX_Tree::CJX_Tree(CXFA_Object* obj) : CJX_Object(obj) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_Tree::~CJX_Tree() {}
+
+void CJX_Tree::resolveNode(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength != 1) {
+    ThrowParamCountMismatchException(L"resolveNode");
+    return;
+  }
+  WideString wsExpression =
+      WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringView());
+  CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
+  if (!pScriptContext)
+    return;
+  CXFA_Object* refNode = GetXFAObject();
+  if (refNode->GetElementType() == XFA_Element::Xfa)
+    refNode = pScriptContext->GetThisObject();
+  uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
+                    XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
+                    XFA_RESOLVENODE_Siblings;
+  XFA_RESOLVENODE_RS resolveNodeRS;
+  if (!pScriptContext->ResolveObjects(ToNode(refNode),
+                                      wsExpression.AsStringView(),
+                                      &resolveNodeRS, dwFlag, nullptr)) {
+    pArguments->GetReturnValue()->SetNull();
+    return;
+  }
+  if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
+    CXFA_Object* pObject = resolveNodeRS.objects.front();
+    pArguments->GetReturnValue()->Assign(
+        pScriptContext->GetJSValueFromMap(pObject));
+  } else {
+    const XFA_SCRIPTATTRIBUTEINFO* lpAttributeInfo =
+        resolveNodeRS.pScriptAttribute;
+    if (lpAttributeInfo &&
+        lpAttributeInfo->eValueType == XFA_ScriptType::Object) {
+      auto pValue =
+          pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetRuntime());
+      CJX_Object* jsObject = resolveNodeRS.objects.front()->JSObject();
+      (jsObject->*(lpAttributeInfo->callback))(pValue.get(), false,
+                                               lpAttributeInfo->attribute);
+      pArguments->GetReturnValue()->Assign(pValue.get());
+    } else {
+      pArguments->GetReturnValue()->SetNull();
+    }
+  }
+}
+
+void CJX_Tree::resolveNodes(CFXJSE_Arguments* pArguments) {
+  int32_t iLength = pArguments->GetLength();
+  if (iLength != 1) {
+    ThrowParamCountMismatchException(L"resolveNodes");
+    return;
+  }
+
+  WideString wsExpression =
+      WideString::FromUTF8(pArguments->GetUTF8String(0).AsStringView());
+  CFXJSE_Value* pValue = pArguments->GetReturnValue();
+  if (!pValue)
+    return;
+
+  CXFA_Object* refNode = GetXFAObject();
+  if (refNode->GetElementType() == XFA_Element::Xfa)
+    refNode = GetDocument()->GetScriptContext()->GetThisObject();
+
+  ResolveNodeList(pValue, wsExpression,
+                  XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
+                      XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
+                      XFA_RESOLVENODE_Siblings,
+                  ToNode(refNode));
+}
+
+void CJX_Tree::all(CFXJSE_Value* pValue,
+                   bool bSetting,
+                   XFA_Attribute eAttribute) {
+  if (bSetting) {
+    ThrowInvalidPropertyException();
+    return;
+  }
+
+  uint32_t dwFlag = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL;
+  WideString wsExpression = GetAttribute(XFA_Attribute::Name) + L"[*]";
+  ResolveNodeList(pValue, wsExpression, dwFlag, nullptr);
+}
+
+void CJX_Tree::classAll(CFXJSE_Value* pValue,
+                        bool bSetting,
+                        XFA_Attribute eAttribute) {
+  if (bSetting) {
+    ThrowInvalidPropertyException();
+    return;
+  }
+
+  WideString wsExpression = L"#" + GetXFAObject()->GetClassName() + L"[*]";
+  ResolveNodeList(pValue, wsExpression,
+                  XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_ALL, nullptr);
+}
+
+void CJX_Tree::nodes(CFXJSE_Value* pValue,
+                     bool bSetting,
+                     XFA_Attribute eAttribute) {
+  CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
+  if (!pScriptContext)
+    return;
+
+  if (bSetting) {
+    WideString wsMessage = L"Unable to set ";
+    FXJSE_ThrowMessage(wsMessage.UTF8Encode().AsStringView());
+    return;
+  }
+
+  CXFA_AttachNodeList* pNodeList =
+      new CXFA_AttachNodeList(GetDocument(), ToNode(GetXFAObject()));
+  pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
+}
+
+void CJX_Tree::parent(CFXJSE_Value* pValue,
+                      bool bSetting,
+                      XFA_Attribute eAttribute) {
+  if (bSetting) {
+    ThrowInvalidPropertyException();
+    return;
+  }
+
+  CXFA_Node* pParent = ToNode(GetXFAObject())->GetNodeItem(XFA_NODEITEM_Parent);
+  if (!pParent) {
+    pValue->SetNull();
+    return;
+  }
+
+  pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pParent));
+}
+
+void CJX_Tree::index(CFXJSE_Value* pValue,
+                     bool bSetting,
+                     XFA_Attribute eAttribute) {
+  if (bSetting) {
+    ThrowInvalidPropertyException();
+    return;
+  }
+  pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameNameIndex());
+}
+
+void CJX_Tree::classIndex(CFXJSE_Value* pValue,
+                          bool bSetting,
+                          XFA_Attribute eAttribute) {
+  if (bSetting) {
+    ThrowInvalidPropertyException();
+    return;
+  }
+  pValue->SetInteger(ToNode(GetXFAObject())->GetNodeSameClassIndex());
+}
+
+void CJX_Tree::somExpression(CFXJSE_Value* pValue,
+                             bool bSetting,
+                             XFA_Attribute eAttribute) {
+  if (bSetting) {
+    ThrowInvalidPropertyException();
+    return;
+  }
+
+  WideString wsSOMExpression;
+  GetXFAObject()->GetSOMExpression(wsSOMExpression);
+  pValue->SetString(wsSOMExpression.UTF8Encode().AsStringView());
+}
+
+void CJX_Tree::ResolveNodeList(CFXJSE_Value* pValue,
+                               WideString wsExpression,
+                               uint32_t dwFlag,
+                               CXFA_Node* refNode) {
+  CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
+  if (!pScriptContext)
+    return;
+  if (!refNode)
+    refNode = ToNode(GetXFAObject());
+
+  XFA_RESOLVENODE_RS resolveNodeRS;
+  pScriptContext->ResolveObjects(refNode, wsExpression.AsStringView(),
+                                 &resolveNodeRS, dwFlag, nullptr);
+  CXFA_ArrayNodeList* pNodeList = new CXFA_ArrayNodeList(GetDocument());
+  if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
+    for (CXFA_Object* pObject : resolveNodeRS.objects) {
+      if (pObject->IsNode())
+        pNodeList->Append(pObject->AsNode());
+    }
+  } else {
+    if (resolveNodeRS.pScriptAttribute &&
+        resolveNodeRS.pScriptAttribute->eValueType == XFA_ScriptType::Object) {
+      for (CXFA_Object* pObject : resolveNodeRS.objects) {
+        auto pValue =
+            pdfium::MakeUnique<CFXJSE_Value>(pScriptContext->GetRuntime());
+        CJX_Object* jsObject = pObject->JSObject();
+        (jsObject->*(resolveNodeRS.pScriptAttribute->callback))(
+            pValue.get(), false, resolveNodeRS.pScriptAttribute->attribute);
+
+        CXFA_Object* obj = CFXJSE_Engine::ToObject(pValue.get(), nullptr);
+        if (obj->IsNode())
+          pNodeList->Append(obj->AsNode());
+      }
+    }
+  }
+  pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
+}
diff --git a/fxjs/xfa/cjx_tree.h b/fxjs/xfa/cjx_tree.h
new file mode 100644
index 0000000..3008112
--- /dev/null
+++ b/fxjs/xfa/cjx_tree.h
@@ -0,0 +1,45 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_TREE_H_
+#define FXJS_XFA_CJX_TREE_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_object.h"
+
+class CXFA_Object;
+class CXFA_Node;
+
+class CJX_Tree : public CJX_Object {
+ public:
+  explicit CJX_Tree(CXFA_Object* obj);
+  ~CJX_Tree() override;
+
+  JS_METHOD(resolveNode, CJX_Tree);
+  JS_METHOD(resolveNodes, CJX_Tree);
+
+  void all(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
+  void nodes(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
+  void classAll(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
+  void parent(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
+  void index(CFXJSE_Value* pValue, bool bSetting, XFA_Attribute eAttribute);
+  void classIndex(CFXJSE_Value* pValue,
+                  bool bSetting,
+                  XFA_Attribute eAttribute);
+  void somExpression(CFXJSE_Value* pValue,
+                     bool bSetting,
+                     XFA_Attribute eAttribute);
+
+ private:
+  void ResolveNodeList(CFXJSE_Value* pValue,
+                       WideString wsExpression,
+                       uint32_t dwFlag,
+                       CXFA_Node* refNode);
+
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_TREE_H_
diff --git a/fxjs/xfa/cjx_treelist.cpp b/fxjs/xfa/cjx_treelist.cpp
new file mode 100644
index 0000000..f82f30d
--- /dev/null
+++ b/fxjs/xfa/cjx_treelist.cpp
@@ -0,0 +1,45 @@
+// 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_treelist.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxfa/parser/cxfa_treelist.h"
+
+const CJX_MethodSpec CJX_TreeList::MethodSpecs[] = {
+    {"namedItem", namedItem_static},
+    {"", nullptr}};
+
+CJX_TreeList::CJX_TreeList(CXFA_TreeList* list) : CJX_List(list) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_TreeList::~CJX_TreeList() {}
+
+CXFA_TreeList* CJX_TreeList::GetXFATreeList() {
+  return static_cast<CXFA_TreeList*>(GetXFAObject());
+}
+
+void CJX_TreeList::namedItem(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 1) {
+    ThrowParamCountMismatchException(L"namedItem");
+    return;
+  }
+
+  ByteString szName = pArguments->GetUTF8String(0);
+  CXFA_Node* pNode = GetXFATreeList()->NamedItem(
+      WideString::FromUTF8(szName.AsStringView()).AsStringView());
+  if (!pNode)
+    return;
+
+  pArguments->GetReturnValue()->Assign(
+      GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode));
+}
diff --git a/fxjs/xfa/cjx_treelist.h b/fxjs/xfa/cjx_treelist.h
new file mode 100644
index 0000000..29a95e6
--- /dev/null
+++ b/fxjs/xfa/cjx_treelist.h
@@ -0,0 +1,28 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_TREELIST_H_
+#define FXJS_XFA_CJX_TREELIST_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/xfa/cjx_list.h"
+
+class CXFA_TreeList;
+
+class CJX_TreeList : public CJX_List {
+ public:
+  explicit CJX_TreeList(CXFA_TreeList* list);
+  ~CJX_TreeList() override;
+
+  JS_METHOD(namedItem, CJX_TreeList);
+
+ private:
+  CXFA_TreeList* GetXFATreeList();
+
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_TREELIST_H_
diff --git a/fxjs/xfa/cjx_wsdlconnection.cpp b/fxjs/xfa/cjx_wsdlconnection.cpp
new file mode 100644
index 0000000..8a684f4
--- /dev/null
+++ b/fxjs/xfa/cjx_wsdlconnection.cpp
@@ -0,0 +1,31 @@
+// 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_wsdlconnection.h"
+
+#include "fxjs/cfxjse_arguments.h"
+#include "fxjs/cfxjse_value.h"
+#include "xfa/fxfa/parser/cxfa_wsdlconnection.h"
+
+const CJX_MethodSpec CJX_WsdlConnection::MethodSpecs[] = {
+    {"execute", execute_static},
+    {"", nullptr}};
+
+CJX_WsdlConnection::CJX_WsdlConnection(CXFA_WsdlConnection* connection)
+    : CJX_Node(connection) {
+  DefineMethods(MethodSpecs);
+}
+
+CJX_WsdlConnection::~CJX_WsdlConnection() {}
+
+void CJX_WsdlConnection::execute(CFXJSE_Arguments* pArguments) {
+  int32_t argc = pArguments->GetLength();
+  if (argc != 0 && argc != 1) {
+    ThrowParamCountMismatchException(L"execute");
+    return;
+  }
+  pArguments->GetReturnValue()->SetBoolean(false);
+}
diff --git a/fxjs/xfa/cjx_wsdlconnection.h b/fxjs/xfa/cjx_wsdlconnection.h
new file mode 100644
index 0000000..76533ce
--- /dev/null
+++ b/fxjs/xfa/cjx_wsdlconnection.h
@@ -0,0 +1,26 @@
+// 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
+
+#ifndef FXJS_XFA_CJX_WSDLCONNECTION_H_
+#define FXJS_XFA_CJX_WSDLCONNECTION_H_
+
+#include "fxjs/CJX_Define.h"
+#include "fxjs/cjx_node.h"
+
+class CXFA_WsdlConnection;
+
+class CJX_WsdlConnection : public CJX_Node {
+ public:
+  explicit CJX_WsdlConnection(CXFA_WsdlConnection* connection);
+  ~CJX_WsdlConnection() override;
+
+  JS_METHOD(execute, CJX_WsdlConnection);
+
+ private:
+  static const CJX_MethodSpec MethodSpecs[];
+};
+
+#endif  // FXJS_XFA_CJX_WSDLCONNECTION_H_
diff --git a/xfa/fxfa/cxfa_ffdoc.h b/xfa/fxfa/cxfa_ffdoc.h
index 475ead3..e183568 100644
--- a/xfa/fxfa/cxfa_ffdoc.h
+++ b/xfa/fxfa/cxfa_ffdoc.h
@@ -17,6 +17,7 @@
 
 class CFGAS_PDFFontMgr;
 class CFX_ChecksumContext;
+class CPDF_Document;
 class CXFA_FFApp;
 class CXFA_FFNotify;
 class CXFA_FFDocView;
diff --git a/xfa/fxfa/cxfa_ffwidget.h b/xfa/fxfa/cxfa_ffwidget.h
index e9f88e9..a258e02 100644
--- a/xfa/fxfa/cxfa_ffwidget.h
+++ b/xfa/fxfa/cxfa_ffwidget.h
@@ -19,6 +19,7 @@
 class CXFA_FFDocView;
 class CXFA_FFDoc;
 class CXFA_FFApp;
+class CXFA_Graphics;
 enum class FWL_WidgetHit;
 
 inline float XFA_UnitPx2Pt(float fPx, float fDpi) {
diff --git a/xfa/fxfa/cxfa_ffwidgethandler.h b/xfa/fxfa/cxfa_ffwidgethandler.h
index e2b50dc..1ef8854 100644
--- a/xfa/fxfa/cxfa_ffwidgethandler.h
+++ b/xfa/fxfa/cxfa_ffwidgethandler.h
@@ -14,6 +14,7 @@
 #include "xfa/fxfa/parser/cxfa_document.h"
 
 class CXFA_FFDocView;
+class CXFA_Graphics;
 enum class FWL_WidgetHit;
 
 class CXFA_FFWidgetHandler {
diff --git a/xfa/fxfa/cxfa_rendercontext.h b/xfa/fxfa/cxfa_rendercontext.h
index 8f9ef3d..411830d 100644
--- a/xfa/fxfa/cxfa_rendercontext.h
+++ b/xfa/fxfa/cxfa_rendercontext.h
@@ -11,6 +11,8 @@
 
 #include "xfa/fxfa/fxfa.h"
 
+class CXFA_Graphics;
+
 class CXFA_RenderContext {
  public:
   CXFA_RenderContext(CXFA_FFPageView* pPageView,
diff --git a/xfa/fxfa/fxfa.h b/xfa/fxfa/fxfa.h
index b0f70f1..c81a9c2 100644
--- a/xfa/fxfa/fxfa.h
+++ b/xfa/fxfa/fxfa.h
@@ -13,19 +13,10 @@
 #include "xfa/fxfa/cxfa_widgetacc.h"
 #include "xfa/fxfa/fxfa_basic.h"
 
-class CFGAS_GEFont;
-class CXFA_Graphics;
-class CPDF_Document;
 class CXFA_FFPageView;
-class CXFA_Node;
-class CXFA_NodeList;
 class CXFA_WidgetAcc;
 class IFWL_AdapterTimerMgr;
 class IFX_SeekableReadStream;
-class IXFA_AppProvider;
-class IXFA_DocEnvironment;
-class IXFA_WidgetAccIterator;
-class IXFA_WidgetIterator;
 
 #define XFA_MBICON_Error 0
 #define XFA_MBICON_Warning 1
diff --git a/xfa/fxfa/fxfa_basic.h b/xfa/fxfa/fxfa_basic.h
index 1f375cd..b5acd2d 100644
--- a/xfa/fxfa/fxfa_basic.h
+++ b/xfa/fxfa/fxfa_basic.h
@@ -831,7 +831,7 @@
   CompressObjectStream,
   DataValue,
   AccessibleContent,
-  NodeList,
+  TreeList,
   IncludeXDPContent,
   XmlConnection,
   ValidateApprovalSignatures,
@@ -939,8 +939,6 @@
 };
 
 struct XFA_SCRIPTHIERARCHY {
-  uint16_t wMethodStart;
-  uint16_t wMethodCount;
   uint16_t wAttributeStart;
   uint16_t wAttributeCount;
   int16_t wParentIndex;
diff --git a/xfa/fxfa/parser/cxfa_area.cpp b/xfa/fxfa/parser/cxfa_area.cpp
index c242e31..6534ac3 100644
--- a/xfa/fxfa/parser/cxfa_area.cpp
+++ b/xfa/fxfa/parser/cxfa_area.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_area.h"
 
+#include "fxjs/xfa/cjx_container.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Desc, 1, 0},
@@ -37,6 +40,7 @@
           XFA_Element::Area,
           kPropertyData,
           kAttributeData,
-          kName) {}
+          kName,
+          pdfium::MakeUnique<CJX_Container>(this)) {}
 
 CXFA_Area::~CXFA_Area() {}
diff --git a/xfa/fxfa/parser/cxfa_arraynodelist.cpp b/xfa/fxfa/parser/cxfa_arraynodelist.cpp
index 03966c3..3b32d8f 100644
--- a/xfa/fxfa/parser/cxfa_arraynodelist.cpp
+++ b/xfa/fxfa/parser/cxfa_arraynodelist.cpp
@@ -11,7 +11,7 @@
 #include "third_party/base/stl_util.h"
 
 CXFA_ArrayNodeList::CXFA_ArrayNodeList(CXFA_Document* pDocument)
-    : CXFA_NodeList(pDocument) {}
+    : CXFA_TreeList(pDocument) {}
 
 CXFA_ArrayNodeList::~CXFA_ArrayNodeList() {}
 
diff --git a/xfa/fxfa/parser/cxfa_arraynodelist.h b/xfa/fxfa/parser/cxfa_arraynodelist.h
index ba00f30..0ebe0c6 100644
--- a/xfa/fxfa/parser/cxfa_arraynodelist.h
+++ b/xfa/fxfa/parser/cxfa_arraynodelist.h
@@ -9,17 +9,17 @@
 
 #include <vector>
 
-#include "xfa/fxfa/parser/cxfa_nodelist.h"
+#include "xfa/fxfa/parser/cxfa_treelist.h"
 
 class CXFA_Document;
 class CXFA_Node;
 
-class CXFA_ArrayNodeList : public CXFA_NodeList {
+class CXFA_ArrayNodeList : public CXFA_TreeList {
  public:
   explicit CXFA_ArrayNodeList(CXFA_Document* pDocument);
   ~CXFA_ArrayNodeList() override;
 
-  // From CXFA_NodeList.
+  // From CXFA_TreeList.
   int32_t GetLength() override;
   bool Append(CXFA_Node* pNode) override;
   bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override;
diff --git a/xfa/fxfa/parser/cxfa_attachnodelist.cpp b/xfa/fxfa/parser/cxfa_attachnodelist.cpp
index 6340377..a793e02 100644
--- a/xfa/fxfa/parser/cxfa_attachnodelist.cpp
+++ b/xfa/fxfa/parser/cxfa_attachnodelist.cpp
@@ -10,7 +10,7 @@
 
 CXFA_AttachNodeList::CXFA_AttachNodeList(CXFA_Document* pDocument,
                                          CXFA_Node* pAttachNode)
-    : CXFA_NodeList(pDocument) {
+    : CXFA_TreeList(pDocument) {
   m_pAttachNode = pAttachNode;
 }
 
diff --git a/xfa/fxfa/parser/cxfa_attachnodelist.h b/xfa/fxfa/parser/cxfa_attachnodelist.h
index 3bb771a..a657150 100644
--- a/xfa/fxfa/parser/cxfa_attachnodelist.h
+++ b/xfa/fxfa/parser/cxfa_attachnodelist.h
@@ -7,16 +7,16 @@
 #ifndef XFA_FXFA_PARSER_CXFA_ATTACHNODELIST_H_
 #define XFA_FXFA_PARSER_CXFA_ATTACHNODELIST_H_
 
-#include "xfa/fxfa/parser/cxfa_nodelist.h"
+#include "xfa/fxfa/parser/cxfa_treelist.h"
 
 class CXFA_Document;
 class CXFA_Node;
 
-class CXFA_AttachNodeList : public CXFA_NodeList {
+class CXFA_AttachNodeList : public CXFA_TreeList {
  public:
   CXFA_AttachNodeList(CXFA_Document* pDocument, CXFA_Node* pAttachNode);
 
-  // From CXFA_NodeList.
+  // From CXFA_TreeList.
   int32_t GetLength() override;
   bool Append(CXFA_Node* pNode) override;
   bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) override;
diff --git a/xfa/fxfa/parser/cxfa_boolean.cpp b/xfa/fxfa/parser/cxfa_boolean.cpp
index 74fe2be..27931b1 100644
--- a/xfa/fxfa/parser/cxfa_boolean.cpp
+++ b/xfa/fxfa/parser/cxfa_boolean.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_boolean.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -28,6 +31,7 @@
                 XFA_Element::Boolean,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_Boolean::~CXFA_Boolean() {}
diff --git a/xfa/fxfa/parser/cxfa_certificate.cpp b/xfa/fxfa/parser/cxfa_certificate.cpp
index d512bf3..65d555b 100644
--- a/xfa/fxfa/parser/cxfa_certificate.cpp
+++ b/xfa/fxfa/parser/cxfa_certificate.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_certificate.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Certificate,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Certificate::~CXFA_Certificate() {}
diff --git a/xfa/fxfa/parser/cxfa_connectionset.cpp b/xfa/fxfa/parser/cxfa_connectionset.cpp
index 6dc86b4..78f02e0 100644
--- a/xfa/fxfa/parser/cxfa_connectionset.cpp
+++ b/xfa/fxfa/parser/cxfa_connectionset.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_connectionset.h"
 
+#include "fxjs/xfa/cjx_model.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 constexpr wchar_t kName[] = L"connectionSet";
@@ -21,6 +24,7 @@
                 XFA_Element::ConnectionSet,
                 nullptr,
                 nullptr,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Model>(this)) {}
 
 CXFA_ConnectionSet::~CXFA_ConnectionSet() {}
diff --git a/xfa/fxfa/parser/cxfa_contentarea.cpp b/xfa/fxfa/parser/cxfa_contentarea.cpp
index 45e2a3e..6bf1a0c 100644
--- a/xfa/fxfa/parser/cxfa_contentarea.cpp
+++ b/xfa/fxfa/parser/cxfa_contentarea.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_contentarea.h"
 
+#include "fxjs/xfa/cjx_container.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Desc, 1, 0},
@@ -35,6 +38,7 @@
                 XFA_Element::ContentArea,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Container>(this)) {}
 
 CXFA_ContentArea::~CXFA_ContentArea() {}
diff --git a/xfa/fxfa/parser/cxfa_datamodel.cpp b/xfa/fxfa/parser/cxfa_datamodel.cpp
index bda8ab5..686ba4c 100644
--- a/xfa/fxfa/parser/cxfa_datamodel.cpp
+++ b/xfa/fxfa/parser/cxfa_datamodel.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_datamodel.h"
 
+#include "fxjs/xfa/cjx_model.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 constexpr wchar_t kName[] = L"dataModel";
@@ -20,6 +23,7 @@
                 XFA_Element::DataModel,
                 nullptr,
                 nullptr,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Model>(this)) {}
 
 CXFA_DataModel::~CXFA_DataModel() {}
diff --git a/xfa/fxfa/parser/cxfa_datawindow.cpp b/xfa/fxfa/parser/cxfa_datawindow.cpp
deleted file mode 100644
index 8be722d..0000000
--- a/xfa/fxfa/parser/cxfa_datawindow.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// 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 "xfa/fxfa/parser/cxfa_datawindow.h"
-
-namespace {
-
-constexpr wchar_t kName[] = L"dataWindow";
-
-}  // namespace
-
-CXFA_DataWindow::CXFA_DataWindow(CXFA_Document* doc, XFA_PacketType packet)
-    : CXFA_Node(doc,
-                packet,
-                XFA_XDPPACKET_Datasets,
-                XFA_ObjectType::Object,
-                XFA_Element::DataWindow,
-                nullptr,
-                nullptr,
-                kName) {}
-
-CXFA_DataWindow::~CXFA_DataWindow() {}
diff --git a/xfa/fxfa/parser/cxfa_datawindow.h b/xfa/fxfa/parser/cxfa_datawindow.h
deleted file mode 100644
index cd2406f..0000000
--- a/xfa/fxfa/parser/cxfa_datawindow.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_PARSER_CXFA_DATAWINDOW_H_
-#define XFA_FXFA_PARSER_CXFA_DATAWINDOW_H_
-
-#include "xfa/fxfa/parser/cxfa_node.h"
-
-class CXFA_DataWindow : public CXFA_Node {
- public:
-  CXFA_DataWindow(CXFA_Document* doc, XFA_PacketType packet);
-  ~CXFA_DataWindow() override;
-};
-
-#endif  // XFA_FXFA_PARSER_CXFA_DATAWINDOW_H_
diff --git a/xfa/fxfa/parser/cxfa_date.cpp b/xfa/fxfa/parser/cxfa_date.cpp
index 671a4d5..94cd872 100644
--- a/xfa/fxfa/parser/cxfa_date.cpp
+++ b/xfa/fxfa/parser/cxfa_date.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_date.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Date,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_Date::~CXFA_Date() {}
diff --git a/xfa/fxfa/parser/cxfa_datetime.cpp b/xfa/fxfa/parser/cxfa_datetime.cpp
index d6f99a0..f25f8f3 100644
--- a/xfa/fxfa/parser/cxfa_datetime.cpp
+++ b/xfa/fxfa/parser/cxfa_datetime.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_datetime.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::DateTime,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_DateTime::~CXFA_DateTime() {}
diff --git a/xfa/fxfa/parser/cxfa_decimal.cpp b/xfa/fxfa/parser/cxfa_decimal.cpp
index a8eaaea..dbdcc39 100644
--- a/xfa/fxfa/parser/cxfa_decimal.cpp
+++ b/xfa/fxfa/parser/cxfa_decimal.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_decimal.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -29,6 +32,7 @@
                 XFA_Element::Decimal,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_Decimal::~CXFA_Decimal() {}
diff --git a/xfa/fxfa/parser/cxfa_delete.cpp b/xfa/fxfa/parser/cxfa_delete.cpp
index b7519e1..ccbba37 100644
--- a/xfa/fxfa/parser/cxfa_delete.cpp
+++ b/xfa/fxfa/parser/cxfa_delete.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_delete.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Delete,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Delete::~CXFA_Delete() {}
diff --git a/xfa/fxfa/parser/cxfa_delta.cpp b/xfa/fxfa/parser/cxfa_delta.cpp
index 4d472b8..4b5bf77 100644
--- a/xfa/fxfa/parser/cxfa_delta.cpp
+++ b/xfa/fxfa/parser/cxfa_delta.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_delta.h"
 
+#include "fxjs/xfa/cjx_delta.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 constexpr wchar_t kName[] = L"delta";
@@ -20,6 +23,7 @@
                 XFA_Element::Delta,
                 nullptr,
                 nullptr,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Delta>(this)) {}
 
 CXFA_Delta::~CXFA_Delta() {}
diff --git a/xfa/fxfa/parser/cxfa_desc.cpp b/xfa/fxfa/parser/cxfa_desc.cpp
index 5c9df2c..9cda06d 100644
--- a/xfa/fxfa/parser/cxfa_desc.cpp
+++ b/xfa/fxfa/parser/cxfa_desc.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_desc.h"
 
+#include "fxjs/xfa/cjx_desc.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -33,6 +36,7 @@
                 XFA_Element::Desc,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Desc>(this)) {}
 
 CXFA_Desc::~CXFA_Desc() {}
diff --git a/xfa/fxfa/parser/cxfa_draw.cpp b/xfa/fxfa/parser/cxfa_draw.cpp
index 5d4c29c..1febee0 100644
--- a/xfa/fxfa/parser/cxfa_draw.cpp
+++ b/xfa/fxfa/parser/cxfa_draw.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_draw.h"
 
+#include "fxjs/xfa/cjx_container.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -55,6 +58,7 @@
                 XFA_Element::Draw,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Container>(this)) {}
 
 CXFA_Draw::~CXFA_Draw() {}
diff --git a/xfa/fxfa/parser/cxfa_eventpseudomodel.cpp b/xfa/fxfa/parser/cxfa_eventpseudomodel.cpp
deleted file mode 100644
index b4a5fed..0000000
--- a/xfa/fxfa/parser/cxfa_eventpseudomodel.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 "xfa/fxfa/parser/cxfa_eventpseudomodel.h"
-
-namespace {
-
-constexpr wchar_t kName[] = L"eventPseudoModel";
-
-}  // namespace
-
-CXFA_EventPseudoModel::CXFA_EventPseudoModel(CXFA_Document* doc,
-                                             XFA_PacketType packet)
-    : CXFA_Node(doc,
-                packet,
-                XFA_XDPPACKET_XDP,
-                XFA_ObjectType::Object,
-                XFA_Element::EventPseudoModel,
-                nullptr,
-                nullptr,
-                kName) {}
-
-CXFA_EventPseudoModel::~CXFA_EventPseudoModel() {}
diff --git a/xfa/fxfa/parser/cxfa_eventpseudomodel.h b/xfa/fxfa/parser/cxfa_eventpseudomodel.h
deleted file mode 100644
index 018e2ea..0000000
--- a/xfa/fxfa/parser/cxfa_eventpseudomodel.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_PARSER_CXFA_EVENTPSEUDOMODEL_H_
-#define XFA_FXFA_PARSER_CXFA_EVENTPSEUDOMODEL_H_
-
-#include "xfa/fxfa/parser/cxfa_node.h"
-
-class CXFA_EventPseudoModel : public CXFA_Node {
- public:
-  CXFA_EventPseudoModel(CXFA_Document* doc, XFA_PacketType packet);
-  ~CXFA_EventPseudoModel() override;
-};
-
-#endif  // XFA_FXFA_PARSER_CXFA_EVENTPSEUDOMODEL_H_
diff --git a/xfa/fxfa/parser/cxfa_exclgroup.cpp b/xfa/fxfa/parser/cxfa_exclgroup.cpp
index 745a971..a24dc36 100644
--- a/xfa/fxfa/parser/cxfa_exclgroup.cpp
+++ b/xfa/fxfa/parser/cxfa_exclgroup.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_exclgroup.h"
 
+#include "fxjs/xfa/cjx_exclgroup.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -57,6 +60,7 @@
                 XFA_Element::ExclGroup,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_ExclGroup>(this)) {}
 
 CXFA_ExclGroup::~CXFA_ExclGroup() {}
diff --git a/xfa/fxfa/parser/cxfa_exdata.cpp b/xfa/fxfa/parser/cxfa_exdata.cpp
index f189480..437024f 100644
--- a/xfa/fxfa/parser/cxfa_exdata.cpp
+++ b/xfa/fxfa/parser/cxfa_exdata.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_exdata.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -33,6 +36,7 @@
                 XFA_Element::ExData,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_ExData::~CXFA_ExData() {}
diff --git a/xfa/fxfa/parser/cxfa_field.cpp b/xfa/fxfa/parser/cxfa_field.cpp
index 2b1ef04..56b8d59 100644
--- a/xfa/fxfa/parser/cxfa_field.cpp
+++ b/xfa/fxfa/parser/cxfa_field.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_field.h"
 
+#include "fxjs/xfa/cjx_field.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -60,6 +63,7 @@
                 XFA_Element::Field,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Field>(this)) {}
 
 CXFA_Field::~CXFA_Field() {}
diff --git a/xfa/fxfa/parser/cxfa_float.cpp b/xfa/fxfa/parser/cxfa_float.cpp
index b1b0116..3430a83 100644
--- a/xfa/fxfa/parser/cxfa_float.cpp
+++ b/xfa/fxfa/parser/cxfa_float.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_float.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Float,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_Float::~CXFA_Float() {}
diff --git a/xfa/fxfa/parser/cxfa_form.cpp b/xfa/fxfa/parser/cxfa_form.cpp
index 94068c4..38ce724 100644
--- a/xfa/fxfa/parser/cxfa_form.cpp
+++ b/xfa/fxfa/parser/cxfa_form.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_form.h"
 
+#include "fxjs/xfa/cjx_form.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -24,6 +27,7 @@
                 XFA_Element::Form,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Form>(this)) {}
 
 CXFA_Form::~CXFA_Form() {}
diff --git a/xfa/fxfa/parser/cxfa_handler.cpp b/xfa/fxfa/parser/cxfa_handler.cpp
index 70f40ae..4a7be94 100644
--- a/xfa/fxfa/parser/cxfa_handler.cpp
+++ b/xfa/fxfa/parser/cxfa_handler.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_handler.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -28,6 +31,7 @@
                 XFA_Element::Handler,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Handler::~CXFA_Handler() {}
diff --git a/xfa/fxfa/parser/cxfa_hostpseudomodel.cpp b/xfa/fxfa/parser/cxfa_hostpseudomodel.cpp
deleted file mode 100644
index af85c29..0000000
--- a/xfa/fxfa/parser/cxfa_hostpseudomodel.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 "xfa/fxfa/parser/cxfa_hostpseudomodel.h"
-
-namespace {
-
-constexpr wchar_t kName[] = L"hostPseudoModel";
-
-}  // namespace
-
-CXFA_HostPseudoModel::CXFA_HostPseudoModel(CXFA_Document* doc,
-                                           XFA_PacketType packet)
-    : CXFA_Node(doc,
-                packet,
-                XFA_XDPPACKET_XDP,
-                XFA_ObjectType::Object,
-                XFA_Element::HostPseudoModel,
-                nullptr,
-                nullptr,
-                kName) {}
-
-CXFA_HostPseudoModel::~CXFA_HostPseudoModel() {}
diff --git a/xfa/fxfa/parser/cxfa_hostpseudomodel.h b/xfa/fxfa/parser/cxfa_hostpseudomodel.h
deleted file mode 100644
index 8fabd53..0000000
--- a/xfa/fxfa/parser/cxfa_hostpseudomodel.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_PARSER_CXFA_HOSTPSEUDOMODEL_H_
-#define XFA_FXFA_PARSER_CXFA_HOSTPSEUDOMODEL_H_
-
-#include "xfa/fxfa/parser/cxfa_node.h"
-
-class CXFA_HostPseudoModel : public CXFA_Node {
- public:
-  CXFA_HostPseudoModel(CXFA_Document* doc, XFA_PacketType packet);
-  ~CXFA_HostPseudoModel() override;
-};
-
-#endif  // XFA_FXFA_PARSER_CXFA_HOSTPSEUDOMODEL_H_
diff --git a/xfa/fxfa/parser/cxfa_insert.cpp b/xfa/fxfa/parser/cxfa_insert.cpp
index 42b21eb..a455d78 100644
--- a/xfa/fxfa/parser/cxfa_insert.cpp
+++ b/xfa/fxfa/parser/cxfa_insert.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_insert.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Insert,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Insert::~CXFA_Insert() {}
diff --git a/xfa/fxfa/parser/cxfa_instancemanager.cpp b/xfa/fxfa/parser/cxfa_instancemanager.cpp
index bd37593..1ba5499 100644
--- a/xfa/fxfa/parser/cxfa_instancemanager.cpp
+++ b/xfa/fxfa/parser/cxfa_instancemanager.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_instancemanager.h"
 
+#include "fxjs/xfa/cjx_instancemanager.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Occur, 1, 0},
@@ -27,6 +30,7 @@
                 XFA_Element::InstanceManager,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_InstanceManager>(this)) {}
 
 CXFA_InstanceManager::~CXFA_InstanceManager() {}
diff --git a/xfa/fxfa/parser/cxfa_integer.cpp b/xfa/fxfa/parser/cxfa_integer.cpp
index 7f7b9a8..514ee4e 100644
--- a/xfa/fxfa/parser/cxfa_integer.cpp
+++ b/xfa/fxfa/parser/cxfa_integer.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_integer.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -28,6 +31,7 @@
                 XFA_Element::Integer,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_Integer::~CXFA_Integer() {}
diff --git a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp
index 05485d1..725eb53 100644
--- a/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp
+++ b/xfa/fxfa/parser/cxfa_itemlayoutprocessor.cpp
@@ -2108,7 +2108,7 @@
       CXFA_Node* pBindNode = pNode->GetBindData();
       if (pBindNode) {
         pBindNode->RemoveBindItem(pNode);
-        pNode->JSNode()->SetBindingNode(nullptr);
+        pNode->SetBindingNode(nullptr);
       }
     }
     pNode->SetFlag(XFA_NodeFlag_UnusedNode, true);
diff --git a/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp b/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp
index 452a573..9ee0531 100644
--- a/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp
+++ b/xfa/fxfa/parser/cxfa_layoutpagemgr.cpp
@@ -1699,7 +1699,7 @@
         CXFA_Node* pBindNode = pNode->GetBindData();
         if (pBindNode) {
           pBindNode->RemoveBindItem(pNode);
-          pNode->JSNode()->SetBindingNode(nullptr);
+          pNode->SetBindingNode(nullptr);
         }
       }
       pNode->SetFlag(XFA_NodeFlag_UnusedNode, true);
diff --git a/xfa/fxfa/parser/cxfa_layoutpseudomodel.cpp b/xfa/fxfa/parser/cxfa_layoutpseudomodel.cpp
deleted file mode 100644
index cdf092d..0000000
--- a/xfa/fxfa/parser/cxfa_layoutpseudomodel.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 "xfa/fxfa/parser/cxfa_layoutpseudomodel.h"
-
-namespace {
-
-constexpr wchar_t kName[] = L"layoutPseudoModel";
-
-}  // namespace
-
-CXFA_LayoutPseudoModel::CXFA_LayoutPseudoModel(CXFA_Document* doc,
-                                               XFA_PacketType packet)
-    : CXFA_Node(doc,
-                packet,
-                XFA_XDPPACKET_XDP,
-                XFA_ObjectType::Object,
-                XFA_Element::LayoutPseudoModel,
-                nullptr,
-                nullptr,
-                kName) {}
-
-CXFA_LayoutPseudoModel::~CXFA_LayoutPseudoModel() {}
diff --git a/xfa/fxfa/parser/cxfa_layoutpseudomodel.h b/xfa/fxfa/parser/cxfa_layoutpseudomodel.h
deleted file mode 100644
index 8ffa4bb..0000000
--- a/xfa/fxfa/parser/cxfa_layoutpseudomodel.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_PARSER_CXFA_LAYOUTPSEUDOMODEL_H_
-#define XFA_FXFA_PARSER_CXFA_LAYOUTPSEUDOMODEL_H_
-
-#include "xfa/fxfa/parser/cxfa_node.h"
-
-class CXFA_LayoutPseudoModel : public CXFA_Node {
- public:
-  CXFA_LayoutPseudoModel(CXFA_Document* doc, XFA_PacketType packet);
-  ~CXFA_LayoutPseudoModel() override;
-};
-
-#endif  // XFA_FXFA_PARSER_CXFA_LAYOUTPSEUDOMODEL_H_
diff --git a/xfa/fxfa/parser/cxfa_list.cpp b/xfa/fxfa/parser/cxfa_list.cpp
index 4f8c1c8..3d56cac 100644
--- a/xfa/fxfa/parser/cxfa_list.cpp
+++ b/xfa/fxfa/parser/cxfa_list.cpp
@@ -6,20 +6,22 @@
 
 #include "xfa/fxfa/parser/cxfa_list.h"
 
-namespace {
+#include <utility>
 
-constexpr wchar_t kName[] = L"list";
+#include "core/fxcrt/fx_extension.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/xfa/cjx_treelist.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
 
-}  // namespace
-
-CXFA_List::CXFA_List(CXFA_Document* doc, XFA_PacketType packet)
-    : CXFA_Node(doc,
-                packet,
-                XFA_XDPPACKET_XDP,
-                XFA_ObjectType::List,
-                XFA_Element::List,
-                nullptr,
-                nullptr,
-                kName) {}
+CXFA_List::CXFA_List(CXFA_Document* pDocument, std::unique_ptr<CJX_Object> obj)
+    : CXFA_Object(pDocument,
+                  XFA_ObjectType::List,
+                  XFA_Element::List,
+                  WideStringView(L"list"),
+                  std::move(obj)) {
+  m_pDocument->GetScriptContext()->AddToCacheList(
+      std::unique_ptr<CXFA_List>(this));
+}
 
 CXFA_List::~CXFA_List() {}
diff --git a/xfa/fxfa/parser/cxfa_list.h b/xfa/fxfa/parser/cxfa_list.h
index c282935..2141a8f 100644
--- a/xfa/fxfa/parser/cxfa_list.h
+++ b/xfa/fxfa/parser/cxfa_list.h
@@ -7,12 +7,24 @@
 #ifndef XFA_FXFA_PARSER_CXFA_LIST_H_
 #define XFA_FXFA_PARSER_CXFA_LIST_H_
 
-#include "xfa/fxfa/parser/cxfa_node.h"
+#include <memory>
 
-class CXFA_List : public CXFA_Node {
+#include "xfa/fxfa/parser/cxfa_object.h"
+
+class CXFA_Document;
+
+class CXFA_List : public CXFA_Object {
  public:
-  CXFA_List(CXFA_Document* doc, XFA_PacketType packet);
   ~CXFA_List() override;
+
+  virtual int32_t GetLength() = 0;
+  virtual bool Append(CXFA_Node* pNode) = 0;
+  virtual bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) = 0;
+  virtual bool Remove(CXFA_Node* pNode) = 0;
+  virtual CXFA_Node* Item(int32_t iIndex) = 0;
+
+ protected:
+  CXFA_List(CXFA_Document* doc, std::unique_ptr<CJX_Object> js_obj);
 };
 
 #endif  // XFA_FXFA_PARSER_CXFA_LIST_H_
diff --git a/xfa/fxfa/parser/cxfa_logpseudomodel.cpp b/xfa/fxfa/parser/cxfa_logpseudomodel.cpp
deleted file mode 100644
index c8db05c..0000000
--- a/xfa/fxfa/parser/cxfa_logpseudomodel.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 "xfa/fxfa/parser/cxfa_logpseudomodel.h"
-
-namespace {
-
-constexpr wchar_t kName[] = L"logPseudoModel";
-
-}  // namespace
-
-CXFA_LogPseudoModel::CXFA_LogPseudoModel(CXFA_Document* doc,
-                                         XFA_PacketType packet)
-    : CXFA_Node(doc,
-                packet,
-                XFA_XDPPACKET_XDP,
-                XFA_ObjectType::Object,
-                XFA_Element::LogPseudoModel,
-                nullptr,
-                nullptr,
-                kName) {}
-
-CXFA_LogPseudoModel::~CXFA_LogPseudoModel() {}
diff --git a/xfa/fxfa/parser/cxfa_logpseudomodel.h b/xfa/fxfa/parser/cxfa_logpseudomodel.h
deleted file mode 100644
index 7d24c42..0000000
--- a/xfa/fxfa/parser/cxfa_logpseudomodel.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_PARSER_CXFA_LOGPSEUDOMODEL_H_
-#define XFA_FXFA_PARSER_CXFA_LOGPSEUDOMODEL_H_
-
-#include "xfa/fxfa/parser/cxfa_node.h"
-
-class CXFA_LogPseudoModel : public CXFA_Node {
- public:
-  CXFA_LogPseudoModel(CXFA_Document* doc, XFA_PacketType packet);
-  ~CXFA_LogPseudoModel() override;
-};
-
-#endif  // XFA_FXFA_PARSER_CXFA_LOGPSEUDOMODEL_H_
diff --git a/xfa/fxfa/parser/cxfa_manifest.cpp b/xfa/fxfa/parser/cxfa_manifest.cpp
index 243331c..32ec795 100644
--- a/xfa/fxfa/parser/cxfa_manifest.cpp
+++ b/xfa/fxfa/parser/cxfa_manifest.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_manifest.h"
 
+#include "fxjs/xfa/cjx_manifest.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0},
@@ -31,6 +34,7 @@
                 XFA_Element::Manifest,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Manifest>(this)) {}
 
 CXFA_Manifest::~CXFA_Manifest() {}
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index b296645..b404b34 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -161,12 +161,9 @@
                      XFA_Element eType,
                      const PropertyData* properties,
                      const AttributeData* attributes,
-                     const WideStringView& elementName)
-    : CXFA_Object(pDoc,
-                  oType,
-                  eType,
-                  elementName,
-                  pdfium::MakeUnique<CJX_Node>(this)),
+                     const WideStringView& elementName,
+                     std::unique_ptr<CJX_Object> js_node)
+    : CXFA_Object(pDoc, oType, eType, elementName, std::move(js_node)),
       m_Properties(properties),
       m_Attributes(attributes),
       m_ValidPackets(validPackets),
@@ -182,6 +179,24 @@
   ASSERT(m_pDocument);
 }
 
+CXFA_Node::CXFA_Node(CXFA_Document* pDoc,
+                     XFA_PacketType ePacket,
+                     uint32_t validPackets,
+                     XFA_ObjectType oType,
+                     XFA_Element eType,
+                     const PropertyData* properties,
+                     const AttributeData* attributes,
+                     const WideStringView& elementName)
+    : CXFA_Node(pDoc,
+                ePacket,
+                validPackets,
+                oType,
+                eType,
+                properties,
+                attributes,
+                elementName,
+                pdfium::MakeUnique<CJX_Node>(this)) {}
+
 CXFA_Node::~CXFA_Node() {
   ASSERT(!m_pParent);
 
@@ -230,7 +245,7 @@
     }
   }
   pClone->SetFlag(XFA_NodeFlag_Initialized, true);
-  pClone->JSNode()->SetBindingNode(nullptr);
+  pClone->SetBindingNode(nullptr);
   return pClone;
 }
 
@@ -472,33 +487,32 @@
 
 CXFA_Node* CXFA_Node::GetBindData() {
   ASSERT(GetPacketType() == XFA_PacketType::Form);
-  return JSNode()->GetBindingNode();
+  return GetBindingNode();
 }
 
 std::vector<UnownedPtr<CXFA_Node>>* CXFA_Node::GetBindItems() {
-  return JSNode()->GetBindingNodes();
+  return GetBindingNodes();
 }
 
 int32_t CXFA_Node::AddBindItem(CXFA_Node* pFormNode) {
   ASSERT(pFormNode);
 
   if (BindsFormItems()) {
-    std::vector<UnownedPtr<CXFA_Node>>* nodes = JSNode()->GetBindingNodes();
     bool found = false;
-    for (auto& v : *nodes) {
+    for (auto& v : binding_nodes_) {
       if (v.Get() == pFormNode) {
         found = true;
         break;
       }
     }
     if (!found)
-      nodes->emplace_back(pFormNode);
-    return pdfium::CollectionSize<int32_t>(*nodes);
+      binding_nodes_.emplace_back(pFormNode);
+    return pdfium::CollectionSize<int32_t>(binding_nodes_);
   }
 
-  CXFA_Node* pOldFormItem = JSNode()->GetBindingNode();
+  CXFA_Node* pOldFormItem = GetBindingNode();
   if (!pOldFormItem) {
-    JSNode()->SetBindingNode(pFormNode);
+    SetBindingNode(pFormNode);
     return 1;
   }
   if (pOldFormItem == pFormNode)
@@ -507,7 +521,7 @@
   std::vector<UnownedPtr<CXFA_Node>> items;
   items.emplace_back(pOldFormItem);
   items.emplace_back(pFormNode);
-  JSNode()->SetBindingNodes(std::move(items));
+  SetBindingNodes(std::move(items));
 
   m_uNodeFlags |= XFA_NodeFlag_BindFormItems;
   return 2;
@@ -515,33 +529,30 @@
 
 int32_t CXFA_Node::RemoveBindItem(CXFA_Node* pFormNode) {
   if (BindsFormItems()) {
-    std::vector<UnownedPtr<CXFA_Node>>* nodes = JSNode()->GetBindingNodes();
-
-    auto it = std::find_if(nodes->begin(), nodes->end(),
+    auto it = std::find_if(binding_nodes_.begin(), binding_nodes_.end(),
                            [&pFormNode](const UnownedPtr<CXFA_Node>& node) {
                              return node.Get() == pFormNode;
                            });
-    if (it != nodes->end())
-      nodes->erase(it);
+    if (it != binding_nodes_.end())
+      binding_nodes_.erase(it);
 
-    if (nodes->size() == 1) {
+    if (binding_nodes_.size() == 1) {
       m_uNodeFlags &= ~XFA_NodeFlag_BindFormItems;
       return 1;
     }
-    return pdfium::CollectionSize<int32_t>(*nodes);
+    return pdfium::CollectionSize<int32_t>(binding_nodes_);
   }
 
-  CXFA_Node* pOldFormItem = JSNode()->GetBindingNode();
+  CXFA_Node* pOldFormItem = GetBindingNode();
   if (pOldFormItem != pFormNode)
     return pOldFormItem ? 1 : 0;
 
-  JSNode()->SetBindingNode(nullptr);
+  SetBindingNode(nullptr);
   return 0;
 }
 
 bool CXFA_Node::HasBindItem() {
-  return GetPacketType() == XFA_PacketType::Datasets &&
-         JSNode()->GetBindingNode();
+  return GetPacketType() == XFA_PacketType::Datasets && GetBindingNode();
 }
 
 CXFA_WidgetData* CXFA_Node::GetWidgetData() {
@@ -1023,14 +1034,6 @@
   return pScriptContext->GetIndexByClassName(const_cast<CXFA_Node*>(this));
 }
 
-void CXFA_Node::GetSOMExpression(WideString& wsSOMExpression) {
-  CFXJSE_Engine* pScriptContext = m_pDocument->GetScriptContext();
-  if (!pScriptContext) {
-    return;
-  }
-  pScriptContext->GetSomExpression(this, wsSOMExpression);
-}
-
 CXFA_Node* CXFA_Node::GetInstanceMgrOfSubform() {
   CXFA_Node* pInstanceMgr = nullptr;
   if (m_ePacket == XFA_PacketType::Form) {
@@ -1086,9 +1089,10 @@
 }
 
 void CXFA_Node::ReleaseBindingNodes() {
-  // Clear any binding nodes set on our JS node as we don't necessarily destruct
-  // in an order that makes sense.
-  JSNode()->ReleaseBindingNodes();
+  // Clear any binding nodes as we don't necessarily destruct in an order that
+  // makes sense.
+  for (auto& node : binding_nodes_)
+    node.Release();
 
   for (CXFA_Node* pNode = m_pChild; pNode; pNode = pNode->m_pNext)
     pNode->ReleaseBindingNodes();
@@ -1281,7 +1285,7 @@
         pDataParent->RemoveChild(pDataNode, true);
       }
     }
-    pFormNode->JSNode()->SetBindingNode(nullptr);
+    pFormNode->SetBindingNode(nullptr);
   }
 }
 
@@ -1367,3 +1371,158 @@
     return {data->default_value};
   return {};
 }
+
+void CXFA_Node::SendAttributeChangeMessage(XFA_Attribute eAttribute,
+                                           bool bScriptModify) {
+  CXFA_LayoutProcessor* pLayoutPro = GetDocument()->GetLayoutProcessor();
+  if (!pLayoutPro)
+    return;
+
+  CXFA_FFNotify* pNotify = GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  if (GetPacketType() != XFA_PacketType::Form) {
+    pNotify->OnValueChanged(this, eAttribute, this, this);
+    return;
+  }
+
+  bool bNeedFindContainer = false;
+  switch (GetElementType()) {
+    case XFA_Element::Caption:
+      bNeedFindContainer = true;
+      pNotify->OnValueChanged(this, eAttribute, this,
+                              GetNodeItem(XFA_NODEITEM_Parent));
+      break;
+    case XFA_Element::Font:
+    case XFA_Element::Para: {
+      bNeedFindContainer = true;
+      CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent);
+      if (pParentNode->GetElementType() == XFA_Element::Caption) {
+        pNotify->OnValueChanged(this, eAttribute, pParentNode,
+                                pParentNode->GetNodeItem(XFA_NODEITEM_Parent));
+      } else {
+        pNotify->OnValueChanged(this, eAttribute, this, pParentNode);
+      }
+      break;
+    }
+    case XFA_Element::Margin: {
+      bNeedFindContainer = true;
+      CXFA_Node* pParentNode = GetNodeItem(XFA_NODEITEM_Parent);
+      XFA_Element eParentType = pParentNode->GetElementType();
+      if (pParentNode->IsContainerNode()) {
+        pNotify->OnValueChanged(this, eAttribute, this, pParentNode);
+      } else if (eParentType == XFA_Element::Caption) {
+        pNotify->OnValueChanged(this, eAttribute, pParentNode,
+                                pParentNode->GetNodeItem(XFA_NODEITEM_Parent));
+      } else {
+        CXFA_Node* pNode = pParentNode->GetNodeItem(XFA_NODEITEM_Parent);
+        if (pNode && pNode->GetElementType() == XFA_Element::Ui) {
+          pNotify->OnValueChanged(this, eAttribute, pNode,
+                                  pNode->GetNodeItem(XFA_NODEITEM_Parent));
+        }
+      }
+      break;
+    }
+    case XFA_Element::Comb: {
+      CXFA_Node* pEditNode = GetNodeItem(XFA_NODEITEM_Parent);
+      XFA_Element eUIType = pEditNode->GetElementType();
+      if (pEditNode && (eUIType == XFA_Element::DateTimeEdit ||
+                        eUIType == XFA_Element::NumericEdit ||
+                        eUIType == XFA_Element::TextEdit)) {
+        CXFA_Node* pUINode = pEditNode->GetNodeItem(XFA_NODEITEM_Parent);
+        if (pUINode) {
+          pNotify->OnValueChanged(this, eAttribute, pUINode,
+                                  pUINode->GetNodeItem(XFA_NODEITEM_Parent));
+        }
+      }
+      break;
+    }
+    case XFA_Element::Button:
+    case XFA_Element::Barcode:
+    case XFA_Element::ChoiceList:
+    case XFA_Element::DateTimeEdit:
+    case XFA_Element::NumericEdit:
+    case XFA_Element::PasswordEdit:
+    case XFA_Element::TextEdit: {
+      CXFA_Node* pUINode = GetNodeItem(XFA_NODEITEM_Parent);
+      if (pUINode) {
+        pNotify->OnValueChanged(this, eAttribute, pUINode,
+                                pUINode->GetNodeItem(XFA_NODEITEM_Parent));
+      }
+      break;
+    }
+    case XFA_Element::CheckButton: {
+      bNeedFindContainer = true;
+      CXFA_Node* pUINode = GetNodeItem(XFA_NODEITEM_Parent);
+      if (pUINode) {
+        pNotify->OnValueChanged(this, eAttribute, pUINode,
+                                pUINode->GetNodeItem(XFA_NODEITEM_Parent));
+      }
+      break;
+    }
+    case XFA_Element::Keep:
+    case XFA_Element::Bookend:
+    case XFA_Element::Break:
+    case XFA_Element::BreakAfter:
+    case XFA_Element::BreakBefore:
+    case XFA_Element::Overflow:
+      bNeedFindContainer = true;
+      break;
+    case XFA_Element::Area:
+    case XFA_Element::Draw:
+    case XFA_Element::ExclGroup:
+    case XFA_Element::Field:
+    case XFA_Element::Subform:
+    case XFA_Element::SubformSet:
+      pLayoutPro->AddChangedContainer(this);
+      pNotify->OnValueChanged(this, eAttribute, this, this);
+      break;
+    case XFA_Element::Sharptext:
+    case XFA_Element::Sharpxml:
+    case XFA_Element::SharpxHTML: {
+      CXFA_Node* pTextNode = GetNodeItem(XFA_NODEITEM_Parent);
+      if (!pTextNode)
+        return;
+
+      CXFA_Node* pValueNode = pTextNode->GetNodeItem(XFA_NODEITEM_Parent);
+      if (!pValueNode)
+        return;
+
+      XFA_Element eType = pValueNode->GetElementType();
+      if (eType == XFA_Element::Value) {
+        bNeedFindContainer = true;
+        CXFA_Node* pNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent);
+        if (pNode && pNode->IsContainerNode()) {
+          if (bScriptModify)
+            pValueNode = pNode;
+
+          pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode);
+        } else {
+          pNotify->OnValueChanged(this, eAttribute, pNode,
+                                  pNode->GetNodeItem(XFA_NODEITEM_Parent));
+        }
+      } else {
+        if (eType == XFA_Element::Items) {
+          CXFA_Node* pNode = pValueNode->GetNodeItem(XFA_NODEITEM_Parent);
+          if (pNode && pNode->IsContainerNode()) {
+            pNotify->OnValueChanged(this, eAttribute, pValueNode, pNode);
+          }
+        }
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  if (!bNeedFindContainer)
+    return;
+
+  CXFA_Node* pParent = this;
+  while (pParent && !pParent->IsContainerNode())
+    pParent = pParent->GetNodeItem(XFA_NODEITEM_Parent);
+
+  if (pParent)
+    pLayoutPro->AddChangedContainer(pParent);
+}
diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h
index ab9f5e2..9508dae 100644
--- a/xfa/fxfa/parser/cxfa_node.h
+++ b/xfa/fxfa/parser/cxfa_node.h
@@ -80,6 +80,8 @@
   bool HasPropertyFlags(XFA_Element property, uint8_t flags) const;
   uint8_t PropertyOccuranceCount(XFA_Element property) const;
 
+  void SendAttributeChangeMessage(XFA_Attribute eAttribute, bool bScriptModify);
+
   bool HasAttribute(XFA_Attribute attr) const;
   XFA_Attribute GetAttribute(size_t i) const;
   XFA_AttributeType GetAttributeType(XFA_Attribute type) const;
@@ -114,7 +116,27 @@
   bool IsLayoutGeneratedNode() const {
     return HasFlag(XFA_NodeFlag_LayoutGeneratedNode);
   }
+
+  void SetBindingNodes(std::vector<UnownedPtr<CXFA_Node>> nodes) {
+    binding_nodes_ = std::move(nodes);
+  }
+  std::vector<UnownedPtr<CXFA_Node>>* GetBindingNodes() {
+    return &binding_nodes_;
+  }
+  void SetBindingNode(CXFA_Node* node) {
+    binding_nodes_.clear();
+    if (node)
+      binding_nodes_.emplace_back(node);
+  }
+  CXFA_Node* GetBindingNode() const {
+    if (binding_nodes_.empty())
+      return nullptr;
+    return binding_nodes_[0].Get();
+  }
+  // TODO(dsinclair): This should not be needed. Nodes should get un-bound when
+  // they're deleted instead of us pointing to bad objects.
   void ReleaseBindingNodes();
+
   bool BindsFormItems() const { return HasFlag(XFA_NodeFlag_BindFormItems); }
   bool HasRemovedChildren() const {
     return HasFlag(XFA_NodeFlag_HasRemovedChildren);
@@ -168,7 +190,6 @@
   CXFA_Node* GetNextSameClassSibling(XFA_Element eType) const;
   int32_t GetNodeSameNameIndex() const;
   int32_t GetNodeSameClassIndex() const;
-  void GetSOMExpression(WideString& wsSOMExpression);
   CXFA_Node* GetInstanceMgrOfSubform();
 
   CXFA_Node* GetOccurNode();
@@ -188,6 +209,15 @@
             XFA_Element eType,
             const PropertyData* properties,
             const AttributeData* attributes,
+            const WideStringView& elementName,
+            std::unique_ptr<CJX_Object> js_node);
+  CXFA_Node(CXFA_Document* pDoc,
+            XFA_PacketType ePacket,
+            uint32_t validPackets,
+            XFA_ObjectType oType,
+            XFA_Element eType,
+            const PropertyData* properties,
+            const AttributeData* attributes,
             const WideStringView& elementName);
 
  private:
@@ -212,6 +242,7 @@
   uint16_t m_uNodeFlags;
   uint32_t m_dwNameHash;
   CXFA_Node* m_pAuxNode;
+  std::vector<UnownedPtr<CXFA_Node>> binding_nodes_;
 };
 
 #endif  // XFA_FXFA_PARSER_CXFA_NODE_H_
diff --git a/xfa/fxfa/parser/cxfa_node_statics.cpp b/xfa/fxfa/parser/cxfa_node_statics.cpp
index 2508890..75e512e 100644
--- a/xfa/fxfa/parser/cxfa_node_statics.cpp
+++ b/xfa/fxfa/parser/cxfa_node_statics.cpp
@@ -72,7 +72,6 @@
 #include "xfa/fxfa/parser/cxfa_datagroup.h"
 #include "xfa/fxfa/parser/cxfa_datamodel.h"
 #include "xfa/fxfa/parser/cxfa_datavalue.h"
-#include "xfa/fxfa/parser/cxfa_datawindow.h"
 #include "xfa/fxfa/parser/cxfa_date.h"
 #include "xfa/fxfa/parser/cxfa_datepattern.h"
 #include "xfa/fxfa/parser/cxfa_datepatterns.h"
@@ -115,7 +114,6 @@
 #include "xfa/fxfa/parser/cxfa_era.h"
 #include "xfa/fxfa/parser/cxfa_eranames.h"
 #include "xfa/fxfa/parser/cxfa_event.h"
-#include "xfa/fxfa/parser/cxfa_eventpseudomodel.h"
 #include "xfa/fxfa/parser/cxfa_exclgroup.h"
 #include "xfa/fxfa/parser/cxfa_exclude.h"
 #include "xfa/fxfa/parser/cxfa_excludens.h"
@@ -135,7 +133,6 @@
 #include "xfa/fxfa/parser/cxfa_formfieldfilling.h"
 #include "xfa/fxfa/parser/cxfa_groupparent.h"
 #include "xfa/fxfa/parser/cxfa_handler.h"
-#include "xfa/fxfa/parser/cxfa_hostpseudomodel.h"
 #include "xfa/fxfa/parser/cxfa_hyphenation.h"
 #include "xfa/fxfa/parser/cxfa_ifempty.h"
 #include "xfa/fxfa/parser/cxfa_image.h"
@@ -154,17 +151,14 @@
 #include "xfa/fxfa/parser/cxfa_keyusage.h"
 #include "xfa/fxfa/parser/cxfa_labelprinter.h"
 #include "xfa/fxfa/parser/cxfa_layout.h"
-#include "xfa/fxfa/parser/cxfa_layoutpseudomodel.h"
 #include "xfa/fxfa/parser/cxfa_level.h"
 #include "xfa/fxfa/parser/cxfa_line.h"
 #include "xfa/fxfa/parser/cxfa_linear.h"
 #include "xfa/fxfa/parser/cxfa_linearized.h"
-#include "xfa/fxfa/parser/cxfa_list.h"
 #include "xfa/fxfa/parser/cxfa_locale.h"
 #include "xfa/fxfa/parser/cxfa_localeset.h"
 #include "xfa/fxfa/parser/cxfa_lockdocument.h"
 #include "xfa/fxfa/parser/cxfa_log.h"
-#include "xfa/fxfa/parser/cxfa_logpseudomodel.h"
 #include "xfa/fxfa/parser/cxfa_manifest.h"
 #include "xfa/fxfa/parser/cxfa_map.h"
 #include "xfa/fxfa/parser/cxfa_margin.h"
@@ -253,7 +247,6 @@
 #include "xfa/fxfa/parser/cxfa_sharpxml.h"
 #include "xfa/fxfa/parser/cxfa_signature.h"
 #include "xfa/fxfa/parser/cxfa_signatureproperties.h"
-#include "xfa/fxfa/parser/cxfa_signaturepseudomodel.h"
 #include "xfa/fxfa/parser/cxfa_signdata.h"
 #include "xfa/fxfa/parser/cxfa_signing.h"
 #include "xfa/fxfa/parser/cxfa_silentprint.h"
@@ -391,7 +384,6 @@
     {0x23e27b84 /* typefaces */, XFA_Element::Typefaces},
     {0x23f4aa75 /* subjectDNs */, XFA_Element::SubjectDNs},
     {0x240d5e8e /* issuers */, XFA_Element::Issuers},
-    {0x2457a033 /* signaturePseudoModel */, XFA_Element::SignaturePseudoModel},
     {0x24a52f8a /* wsdlConnection */, XFA_Element::WsdlConnection},
     {0x254ebd07 /* debug */, XFA_Element::Debug},
     {0x2655c66a /* delta */, XFA_Element::Delta},
@@ -425,7 +417,6 @@
     {0x3e1c91c5 /* adjustData */, XFA_Element::AdjustData},
     {0x3e7a9408 /* autoSave */, XFA_Element::AutoSave},
     {0x3ecead94 /* contentArea */, XFA_Element::ContentArea},
-    {0x3ef334e3 /* eventPseudoModel */, XFA_Element::EventPseudoModel},
     {0x3fadaec0 /* wsdlAddress */, XFA_Element::WsdlAddress},
     {0x40623b5b /* solid */, XFA_Element::Solid},
     {0x41f0bd76 /* dateTimeSymbols */, XFA_Element::DateTimeSymbols},
@@ -457,7 +448,6 @@
     {0x5436d198 /* window */, XFA_Element::Window},
     {0x5473b6dc /* localeSet */, XFA_Element::LocaleSet},
     {0x56ae179e /* handler */, XFA_Element::Handler},
-    {0x5700bd5f /* hostPseudoModel */, XFA_Element::HostPseudoModel},
     {0x570ce835 /* presence */, XFA_Element::Presence},
     {0x5779d65f /* record */, XFA_Element::Record},
     {0x59c8f27d /* embed */, XFA_Element::Embed},
@@ -476,7 +466,6 @@
     {0x67fe7334 /* traversal */, XFA_Element::Traversal},
     {0x6894589c /* silentPrint */, XFA_Element::SilentPrint},
     {0x68a16bbd /* webClient */, XFA_Element::WebClient},
-    {0x69f115df /* layoutPseudoModel */, XFA_Element::LayoutPseudoModel},
     {0x6a4bc084 /* producer */, XFA_Element::Producer},
     {0x6a9e04c9 /* corner */, XFA_Element::Corner},
     {0x6ccd7274 /* msgId */, XFA_Element::MsgId},
@@ -506,7 +495,6 @@
     {0x803d5bbc /* acrobat */, XFA_Element::Acrobat},
     {0x821d6569 /* validationMessaging */, XFA_Element::ValidationMessaging},
     {0x830e688f /* signing */, XFA_Element::Signing},
-    {0x83a550d2 /* dataWindow */, XFA_Element::DataWindow},
     {0x83dab9f5 /* script */, XFA_Element::Script},
     {0x8411ebcd /* addViewerPreferences */, XFA_Element::AddViewerPreferences},
     {0x8777642e /* alwaysEmbed */, XFA_Element::AlwaysEmbed},
@@ -588,7 +576,6 @@
     {0xd1227e6f /* trace */, XFA_Element::Trace},
     {0xd1532876 /* float */, XFA_Element::Float},
     {0xd17a6c30 /* renderPolicy */, XFA_Element::RenderPolicy},
-    {0xd4bf6823 /* logPseudoModel */, XFA_Element::LogPseudoModel},
     {0xd58aa962 /* destination */, XFA_Element::Destination},
     {0xd6e27f1d /* value */, XFA_Element::Value},
     {0xd7a14462 /* bookend */, XFA_Element::Bookend},
@@ -629,7 +616,6 @@
     {0xf1433e88 /* lockDocument */, XFA_Element::LockDocument},
     {0xf54eb997 /* breakAfter */, XFA_Element::BreakAfter},
     {0xf616da28 /* line */, XFA_Element::Line},
-    {0xf616f3dc /* list */, XFA_Element::List},
     {0xf7055fb1 /* source */, XFA_Element::Source},
     {0xf7eebe1c /* occur */, XFA_Element::Occur},
     {0xf8d10d97 /* pickTrayByPDFSize */, XFA_Element::PickTrayByPDFSize},
@@ -923,7 +909,6 @@
 std::unique_ptr<CXFA_Node> CXFA_Node::Create(CXFA_Document* doc,
                                              XFA_Element element,
                                              XFA_PacketType packet) {
-  ASSERT(element != XFA_Element::NodeList);
   std::unique_ptr<CXFA_Node> node;
   switch (element) {
     case XFA_Element::Ps:
@@ -1121,9 +1106,6 @@
     case XFA_Element::Issuers:
       node = pdfium::MakeUnique<CXFA_Issuers>(doc, packet);
       break;
-    case XFA_Element::SignaturePseudoModel:
-      node = pdfium::MakeUnique<CXFA_SignaturePseudoModel>(doc, packet);
-      break;
     case XFA_Element::WsdlConnection:
       node = pdfium::MakeUnique<CXFA_WsdlConnection>(doc, packet);
       break;
@@ -1223,9 +1205,6 @@
     case XFA_Element::ContentArea:
       node = pdfium::MakeUnique<CXFA_ContentArea>(doc, packet);
       break;
-    case XFA_Element::EventPseudoModel:
-      node = pdfium::MakeUnique<CXFA_EventPseudoModel>(doc, packet);
-      break;
     case XFA_Element::WsdlAddress:
       node = pdfium::MakeUnique<CXFA_WsdlAddress>(doc, packet);
       break;
@@ -1319,9 +1298,6 @@
     case XFA_Element::Handler:
       node = pdfium::MakeUnique<CXFA_Handler>(doc, packet);
       break;
-    case XFA_Element::HostPseudoModel:
-      node = pdfium::MakeUnique<CXFA_HostPseudoModel>(doc, packet);
-      break;
     case XFA_Element::Presence:
       node = pdfium::MakeUnique<CXFA_Presence>(doc, packet);
       break;
@@ -1376,9 +1352,6 @@
     case XFA_Element::WebClient:
       node = pdfium::MakeUnique<CXFA_WebClient>(doc, packet);
       break;
-    case XFA_Element::LayoutPseudoModel:
-      node = pdfium::MakeUnique<CXFA_LayoutPseudoModel>(doc, packet);
-      break;
     case XFA_Element::Producer:
       node = pdfium::MakeUnique<CXFA_Producer>(doc, packet);
       break;
@@ -1466,9 +1439,6 @@
     case XFA_Element::Signing:
       node = pdfium::MakeUnique<CXFA_Signing>(doc, packet);
       break;
-    case XFA_Element::DataWindow:
-      node = pdfium::MakeUnique<CXFA_DataWindow>(doc, packet);
-      break;
     case XFA_Element::Script:
       node = pdfium::MakeUnique<CXFA_Script>(doc, packet);
       break;
@@ -1706,9 +1676,6 @@
     case XFA_Element::RenderPolicy:
       node = pdfium::MakeUnique<CXFA_RenderPolicy>(doc, packet);
       break;
-    case XFA_Element::LogPseudoModel:
-      node = pdfium::MakeUnique<CXFA_LogPseudoModel>(doc, packet);
-      break;
     case XFA_Element::Destination:
       node = pdfium::MakeUnique<CXFA_Destination>(doc, packet);
       break;
@@ -1826,9 +1793,6 @@
     case XFA_Element::Line:
       node = pdfium::MakeUnique<CXFA_Line>(doc, packet);
       break;
-    case XFA_Element::List:
-      node = pdfium::MakeUnique<CXFA_List>(doc, packet);
-      break;
     case XFA_Element::Source:
       node = pdfium::MakeUnique<CXFA_Source>(doc, packet);
       break;
@@ -1859,8 +1823,7 @@
     case XFA_Element::Items:
       node = pdfium::MakeUnique<CXFA_Items>(doc, packet);
       break;
-    case XFA_Element::Unknown:
-    case XFA_Element::NodeList:
+    default:
       NOTREACHED();
       return nullptr;
   }
@@ -2500,8 +2463,6 @@
       return L"subjectDNs";
     case XFA_Element::Issuers:
       return L"issuers";
-    case XFA_Element::SignaturePseudoModel:
-      return L"signaturePseudoModel";
     case XFA_Element::WsdlConnection:
       return L"wsdlConnection";
     case XFA_Element::Debug:
@@ -2568,8 +2529,6 @@
       return L"autoSave";
     case XFA_Element::ContentArea:
       return L"contentArea";
-    case XFA_Element::EventPseudoModel:
-      return L"eventPseudoModel";
     case XFA_Element::WsdlAddress:
       return L"wsdlAddress";
     case XFA_Element::Solid:
@@ -2632,8 +2591,6 @@
       return L"localeSet";
     case XFA_Element::Handler:
       return L"handler";
-    case XFA_Element::HostPseudoModel:
-      return L"hostPseudoModel";
     case XFA_Element::Presence:
       return L"presence";
     case XFA_Element::Record:
@@ -2670,8 +2627,6 @@
       return L"silentPrint";
     case XFA_Element::WebClient:
       return L"webClient";
-    case XFA_Element::LayoutPseudoModel:
-      return L"layoutPseudoModel";
     case XFA_Element::Producer:
       return L"producer";
     case XFA_Element::Corner:
@@ -2730,8 +2685,6 @@
       return L"validationMessaging";
     case XFA_Element::Signing:
       return L"signing";
-    case XFA_Element::DataWindow:
-      return L"dataWindow";
     case XFA_Element::Script:
       return L"script";
     case XFA_Element::AddViewerPreferences:
@@ -2890,8 +2843,6 @@
       return L"float";
     case XFA_Element::RenderPolicy:
       return L"renderPolicy";
-    case XFA_Element::LogPseudoModel:
-      return L"logPseudoModel";
     case XFA_Element::Destination:
       return L"destination";
     case XFA_Element::Value:
@@ -2970,8 +2921,6 @@
       return L"breakAfter";
     case XFA_Element::Line:
       return L"line";
-    case XFA_Element::List:
-      return L"list";
     case XFA_Element::Source:
       return L"source";
     case XFA_Element::Occur:
diff --git a/xfa/fxfa/parser/cxfa_nodelist.cpp b/xfa/fxfa/parser/cxfa_nodelist.cpp
deleted file mode 100644
index e05062f..0000000
--- a/xfa/fxfa/parser/cxfa_nodelist.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2016 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 "xfa/fxfa/parser/cxfa_nodelist.h"
-
-#include <memory>
-
-#include "core/fxcrt/fx_extension.h"
-#include "fxjs/cfxjse_engine.h"
-#include "fxjs/cjx_nodelist.h"
-#include "xfa/fxfa/parser/cxfa_document.h"
-#include "xfa/fxfa/parser/cxfa_node.h"
-
-CXFA_NodeList::CXFA_NodeList(CXFA_Document* pDocument)
-    : CXFA_Object(pDocument,
-                  XFA_ObjectType::NodeList,
-                  XFA_Element::NodeList,
-                  WideStringView(L"nodeList"),
-                  pdfium::MakeUnique<CJX_NodeList>(this)) {
-  m_pDocument->GetScriptContext()->AddToCacheList(
-      std::unique_ptr<CXFA_NodeList>(this));
-}
-
-CXFA_NodeList::~CXFA_NodeList() {}
-
-CXFA_Node* CXFA_NodeList::NamedItem(const WideStringView& wsName) {
-  uint32_t dwHashCode = FX_HashCode_GetW(wsName, false);
-  int32_t iCount = GetLength();
-  for (int32_t i = 0; i < iCount; i++) {
-    CXFA_Node* ret = Item(i);
-    if (dwHashCode == ret->GetNameHash())
-      return ret;
-  }
-  return nullptr;
-}
diff --git a/xfa/fxfa/parser/cxfa_nodelist.h b/xfa/fxfa/parser/cxfa_nodelist.h
deleted file mode 100644
index df1c462..0000000
--- a/xfa/fxfa/parser/cxfa_nodelist.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_PARSER_CXFA_NODELIST_H_
-#define XFA_FXFA_PARSER_CXFA_NODELIST_H_
-
-#include "fxjs/cjx_nodelist.h"
-#include "xfa/fxfa/fxfa_basic.h"
-#include "xfa/fxfa/parser/cxfa_object.h"
-
-class CXFA_Node;
-
-class CXFA_NodeList : public CXFA_Object {
- public:
-  explicit CXFA_NodeList(CXFA_Document* pDocument);
-  ~CXFA_NodeList() override;
-
-  CJX_NodeList* JSNodeList() { return static_cast<CJX_NodeList*>(JSObject()); }
-
-  CXFA_Node* NamedItem(const WideStringView& wsName);
-  virtual int32_t GetLength() = 0;
-  virtual bool Append(CXFA_Node* pNode) = 0;
-  virtual bool Insert(CXFA_Node* pNewNode, CXFA_Node* pBeforeNode) = 0;
-  virtual bool Remove(CXFA_Node* pNode) = 0;
-  virtual CXFA_Node* Item(int32_t iIndex) = 0;
-};
-
-#endif  // XFA_FXFA_PARSER_CXFA_NODELIST_H_
diff --git a/xfa/fxfa/parser/cxfa_object.cpp b/xfa/fxfa/parser/cxfa_object.cpp
index 7823015..93d3124 100644
--- a/xfa/fxfa/parser/cxfa_object.cpp
+++ b/xfa/fxfa/parser/cxfa_object.cpp
@@ -9,11 +9,12 @@
 #include <utility>
 
 #include "core/fxcrt/fx_extension.h"
+#include "fxjs/cfxjse_engine.h"
 #include "fxjs/cfxjse_value.h"
 #include "xfa/fxfa/cxfa_ffnotify.h"
 #include "xfa/fxfa/parser/cxfa_document.h"
 #include "xfa/fxfa/parser/cxfa_node.h"
-#include "xfa/fxfa/parser/cxfa_nodelist.h"
+#include "xfa/fxfa/parser/cxfa_treelist.h"
 
 CXFA_Object::CXFA_Object(CXFA_Document* pDocument,
                          XFA_ObjectType objectType,
@@ -30,20 +31,28 @@
 
 CXFA_Object::~CXFA_Object() {}
 
+void CXFA_Object::GetSOMExpression(WideString& wsSOMExpression) {
+  CFXJSE_Engine* pScriptContext = m_pDocument->GetScriptContext();
+  if (!pScriptContext)
+    return;
+
+  pScriptContext->GetSomExpression(ToNode(this), wsSOMExpression);
+}
+
 CXFA_Node* CXFA_Object::AsNode() {
   return IsNode() ? static_cast<CXFA_Node*>(this) : nullptr;
 }
 
-CXFA_NodeList* CXFA_Object::AsNodeList() {
-  return IsNodeList() ? static_cast<CXFA_NodeList*>(this) : nullptr;
+CXFA_TreeList* CXFA_Object::AsTreeList() {
+  return IsTreeList() ? static_cast<CXFA_TreeList*>(this) : nullptr;
 }
 
 const CXFA_Node* CXFA_Object::AsNode() const {
   return IsNode() ? static_cast<const CXFA_Node*>(this) : nullptr;
 }
 
-const CXFA_NodeList* CXFA_Object::AsNodeList() const {
-  return IsNodeList() ? static_cast<const CXFA_NodeList*>(this) : nullptr;
+const CXFA_TreeList* CXFA_Object::AsTreeList() const {
+  return IsTreeList() ? static_cast<const CXFA_TreeList*>(this) : nullptr;
 }
 
 CXFA_Node* ToNode(CXFA_Object* pObj) {
diff --git a/xfa/fxfa/parser/cxfa_object.h b/xfa/fxfa/parser/cxfa_object.h
index a53328d..ce9ce93 100644
--- a/xfa/fxfa/parser/cxfa_object.h
+++ b/xfa/fxfa/parser/cxfa_object.h
@@ -16,12 +16,12 @@
 enum class XFA_ObjectType {
   Object,
   List,
-  NodeList,
   Node,
   NodeC,
   NodeV,
   ModelNode,
   TextNode,
+  TreeList,
   ContainerNode,
   ContentNode,
   VariablesThis
@@ -30,7 +30,7 @@
 class CJX_Object;
 class CXFA_Document;
 class CXFA_Node;
-class CXFA_NodeList;
+class CXFA_TreeList;
 
 class CXFA_Object : public CFXJSE_HostObject {
  public:
@@ -49,7 +49,7 @@
            m_objectType == XFA_ObjectType::ContentNode ||
            m_objectType == XFA_ObjectType::VariablesThis;
   }
-  bool IsNodeList() const { return m_objectType == XFA_ObjectType::NodeList; }
+  bool IsTreeList() const { return m_objectType == XFA_ObjectType::TreeList; }
   bool IsContentNode() const {
     return m_objectType == XFA_ObjectType::ContentNode;
   }
@@ -63,10 +63,10 @@
   }
 
   CXFA_Node* AsNode();
-  CXFA_NodeList* AsNodeList();
+  CXFA_TreeList* AsTreeList();
 
   const CXFA_Node* AsNode() const;
-  const CXFA_NodeList* AsNodeList() const;
+  const CXFA_TreeList* AsTreeList() const;
 
   CJX_Object* JSObject() { return m_pJSObject.get(); }
   const CJX_Object* JSObject() const { return m_pJSObject.get(); }
@@ -75,6 +75,8 @@
   WideStringView GetClassName() const { return m_elementName; }
   uint32_t GetClassHashCode() const { return m_elementNameHash; }
 
+  void GetSOMExpression(WideString& wsSOMExpression);
+
  protected:
   CXFA_Object(CXFA_Document* pDocument,
               XFA_ObjectType objectType,
diff --git a/xfa/fxfa/parser/cxfa_oid.cpp b/xfa/fxfa/parser/cxfa_oid.cpp
index be0d12f..ad61086 100644
--- a/xfa/fxfa/parser/cxfa_oid.cpp
+++ b/xfa/fxfa/parser/cxfa_oid.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_oid.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Oid,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Oid::~CXFA_Oid() {}
diff --git a/xfa/fxfa/parser/cxfa_operation.cpp b/xfa/fxfa/parser/cxfa_operation.cpp
index 3fd753c..7364e96 100644
--- a/xfa/fxfa/parser/cxfa_operation.cpp
+++ b/xfa/fxfa/parser/cxfa_operation.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_operation.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -29,6 +32,7 @@
                 XFA_Element::Operation,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Operation::~CXFA_Operation() {}
diff --git a/xfa/fxfa/parser/cxfa_packet.cpp b/xfa/fxfa/parser/cxfa_packet.cpp
index 646933a..6112271 100644
--- a/xfa/fxfa/parser/cxfa_packet.cpp
+++ b/xfa/fxfa/parser/cxfa_packet.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_packet.h"
 
+#include "fxjs/xfa/cjx_packet.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 constexpr wchar_t kName[] = L"packet";
@@ -20,6 +23,7 @@
                 XFA_Element::Packet,
                 nullptr,
                 nullptr,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Packet>(this)) {}
 
 CXFA_Packet::~CXFA_Packet() {}
diff --git a/xfa/fxfa/parser/cxfa_pagearea.cpp b/xfa/fxfa/parser/cxfa_pagearea.cpp
index b9b7869..ef2ba9e 100644
--- a/xfa/fxfa/parser/cxfa_pagearea.cpp
+++ b/xfa/fxfa/parser/cxfa_pagearea.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_pagearea.h"
 
+#include "fxjs/xfa/cjx_container.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Medium, 1, 0},
@@ -41,6 +44,7 @@
                 XFA_Element::PageArea,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Container>(this)) {}
 
 CXFA_PageArea::~CXFA_PageArea() {}
diff --git a/xfa/fxfa/parser/cxfa_pageset.cpp b/xfa/fxfa/parser/cxfa_pageset.cpp
index 9de123a..536fec1 100644
--- a/xfa/fxfa/parser/cxfa_pageset.cpp
+++ b/xfa/fxfa/parser/cxfa_pageset.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_pageset.h"
 
+#include "fxjs/xfa/cjx_container.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Extras, 1, 0},
@@ -35,6 +38,7 @@
                 XFA_Element::PageSet,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Container>(this)) {}
 
 CXFA_PageSet::~CXFA_PageSet() {}
diff --git a/xfa/fxfa/parser/cxfa_password.cpp b/xfa/fxfa/parser/cxfa_password.cpp
index 1d7a60f..d6f70fb 100644
--- a/xfa/fxfa/parser/cxfa_password.cpp
+++ b/xfa/fxfa/parser/cxfa_password.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_password.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Password,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Password::~CXFA_Password() {}
diff --git a/xfa/fxfa/parser/cxfa_reason.cpp b/xfa/fxfa/parser/cxfa_reason.cpp
index 2d8ab2c..befad7d 100644
--- a/xfa/fxfa/parser/cxfa_reason.cpp
+++ b/xfa/fxfa/parser/cxfa_reason.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_reason.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Reason,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Reason::~CXFA_Reason() {}
diff --git a/xfa/fxfa/parser/cxfa_ref.cpp b/xfa/fxfa/parser/cxfa_ref.cpp
index 51bea82..eea1292 100644
--- a/xfa/fxfa/parser/cxfa_ref.cpp
+++ b/xfa/fxfa/parser/cxfa_ref.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_ref.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -26,6 +29,7 @@
                 XFA_Element::Ref,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Ref::~CXFA_Ref() {}
diff --git a/xfa/fxfa/parser/cxfa_rootelement.cpp b/xfa/fxfa/parser/cxfa_rootelement.cpp
index 7f9e868..5ba4ed3 100644
--- a/xfa/fxfa/parser/cxfa_rootelement.cpp
+++ b/xfa/fxfa/parser/cxfa_rootelement.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_rootelement.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::RootElement,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_RootElement::~CXFA_RootElement() {}
diff --git a/xfa/fxfa/parser/cxfa_select.cpp b/xfa/fxfa/parser/cxfa_select.cpp
index 690413b..7417015 100644
--- a/xfa/fxfa/parser/cxfa_select.cpp
+++ b/xfa/fxfa/parser/cxfa_select.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_select.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Select,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Select::~CXFA_Select() {}
diff --git a/xfa/fxfa/parser/cxfa_signaturepseudomodel.cpp b/xfa/fxfa/parser/cxfa_signaturepseudomodel.cpp
deleted file mode 100644
index 0899e62..0000000
--- a/xfa/fxfa/parser/cxfa_signaturepseudomodel.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 "xfa/fxfa/parser/cxfa_signaturepseudomodel.h"
-
-namespace {
-
-constexpr wchar_t kName[] = L"signaturePseudoModel";
-
-}  // namespace
-
-CXFA_SignaturePseudoModel::CXFA_SignaturePseudoModel(CXFA_Document* doc,
-                                                     XFA_PacketType packet)
-    : CXFA_Node(doc,
-                packet,
-                XFA_XDPPACKET_XDP,
-                XFA_ObjectType::Object,
-                XFA_Element::SignaturePseudoModel,
-                nullptr,
-                nullptr,
-                kName) {}
-
-CXFA_SignaturePseudoModel::~CXFA_SignaturePseudoModel() {}
diff --git a/xfa/fxfa/parser/cxfa_signaturepseudomodel.h b/xfa/fxfa/parser/cxfa_signaturepseudomodel.h
deleted file mode 100644
index bfb3dfb..0000000
--- a/xfa/fxfa/parser/cxfa_signaturepseudomodel.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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
-
-#ifndef XFA_FXFA_PARSER_CXFA_SIGNATUREPSEUDOMODEL_H_
-#define XFA_FXFA_PARSER_CXFA_SIGNATUREPSEUDOMODEL_H_
-
-#include "xfa/fxfa/parser/cxfa_node.h"
-
-class CXFA_SignaturePseudoModel : public CXFA_Node {
- public:
-  CXFA_SignaturePseudoModel(CXFA_Document* doc, XFA_PacketType packet);
-  ~CXFA_SignaturePseudoModel() override;
-};
-
-#endif  // XFA_FXFA_PARSER_CXFA_SIGNATUREPSEUDOMODEL_H_
diff --git a/xfa/fxfa/parser/cxfa_soapaction.cpp b/xfa/fxfa/parser/cxfa_soapaction.cpp
index b6aa0d1..49c0b44 100644
--- a/xfa/fxfa/parser/cxfa_soapaction.cpp
+++ b/xfa/fxfa/parser/cxfa_soapaction.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_soapaction.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::SoapAction,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_SoapAction::~CXFA_SoapAction() {}
diff --git a/xfa/fxfa/parser/cxfa_soapaddress.cpp b/xfa/fxfa/parser/cxfa_soapaddress.cpp
index 9e857ad..9974a48 100644
--- a/xfa/fxfa/parser/cxfa_soapaddress.cpp
+++ b/xfa/fxfa/parser/cxfa_soapaddress.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_soapaddress.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::SoapAddress,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_SoapAddress::~CXFA_SoapAddress() {}
diff --git a/xfa/fxfa/parser/cxfa_source.cpp b/xfa/fxfa/parser/cxfa_source.cpp
index 98f2b94..95d3736 100644
--- a/xfa/fxfa/parser/cxfa_source.cpp
+++ b/xfa/fxfa/parser/cxfa_source.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_source.h"
 
+#include "fxjs/xfa/cjx_source.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {{XFA_Element::Connect, 1, 0},
@@ -29,6 +32,7 @@
                 XFA_Element::Source,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Source>(this)) {}
 
 CXFA_Source::~CXFA_Source() {}
diff --git a/xfa/fxfa/parser/cxfa_sourceset.cpp b/xfa/fxfa/parser/cxfa_sourceset.cpp
index 2617c30..79a498d 100644
--- a/xfa/fxfa/parser/cxfa_sourceset.cpp
+++ b/xfa/fxfa/parser/cxfa_sourceset.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_sourceset.h"
 
+#include "fxjs/xfa/cjx_model.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::SourceSet,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Model>(this)) {}
 
 CXFA_SourceSet::~CXFA_SourceSet() {}
diff --git a/xfa/fxfa/parser/cxfa_speak.cpp b/xfa/fxfa/parser/cxfa_speak.cpp
index b417178..7b3fa36 100644
--- a/xfa/fxfa/parser/cxfa_speak.cpp
+++ b/xfa/fxfa/parser/cxfa_speak.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_speak.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -30,6 +33,7 @@
                 XFA_Element::Speak,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Speak::~CXFA_Speak() {}
diff --git a/xfa/fxfa/parser/cxfa_subform.cpp b/xfa/fxfa/parser/cxfa_subform.cpp
index 6e932f5..7bb7fa7 100644
--- a/xfa/fxfa/parser/cxfa_subform.cpp
+++ b/xfa/fxfa/parser/cxfa_subform.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_subform.h"
 
+#include "fxjs/xfa/cjx_subform.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -68,6 +71,7 @@
                 XFA_Element::Subform,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Subform>(this)) {}
 
 CXFA_Subform::~CXFA_Subform() {}
diff --git a/xfa/fxfa/parser/cxfa_subformset.cpp b/xfa/fxfa/parser/cxfa_subformset.cpp
index 69f8838..d29cbd4 100644
--- a/xfa/fxfa/parser/cxfa_subformset.cpp
+++ b/xfa/fxfa/parser/cxfa_subformset.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_subformset.h"
 
+#include "fxjs/xfa/cjx_container.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -35,6 +38,7 @@
                 XFA_Element::SubformSet,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Container>(this)) {}
 
 CXFA_SubformSet::~CXFA_SubformSet() {}
diff --git a/xfa/fxfa/parser/cxfa_template.cpp b/xfa/fxfa/parser/cxfa_template.cpp
index d847bf8..3f9afa1 100644
--- a/xfa/fxfa/parser/cxfa_template.cpp
+++ b/xfa/fxfa/parser/cxfa_template.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_template.h"
 
+#include "fxjs/xfa/cjx_template.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -33,6 +36,7 @@
           XFA_Element::Template,
           kPropertyData,
           kAttributeData,
-          kName) {}
+          kName,
+          pdfium::MakeUnique<CJX_Template>(this)) {}
 
 CXFA_Template::~CXFA_Template() {}
diff --git a/xfa/fxfa/parser/cxfa_text.cpp b/xfa/fxfa/parser/cxfa_text.cpp
index 80b4eb2..883cdac 100644
--- a/xfa/fxfa/parser/cxfa_text.cpp
+++ b/xfa/fxfa/parser/cxfa_text.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_text.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -30,6 +33,7 @@
                 XFA_Element::Text,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_Text::~CXFA_Text() {}
diff --git a/xfa/fxfa/parser/cxfa_time.cpp b/xfa/fxfa/parser/cxfa_time.cpp
index e4c8705..808ee83 100644
--- a/xfa/fxfa/parser/cxfa_time.cpp
+++ b/xfa/fxfa/parser/cxfa_time.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_time.h"
 
+#include "fxjs/xfa/cjx_content.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Time,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Content>(this)) {}
 
 CXFA_Time::~CXFA_Time() {}
diff --git a/xfa/fxfa/parser/cxfa_tooltip.cpp b/xfa/fxfa/parser/cxfa_tooltip.cpp
index a8721bf..4abcdb9 100644
--- a/xfa/fxfa/parser/cxfa_tooltip.cpp
+++ b/xfa/fxfa/parser/cxfa_tooltip.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_tooltip.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::ToolTip,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_ToolTip::~CXFA_ToolTip() {}
diff --git a/xfa/fxfa/parser/cxfa_treelist.cpp b/xfa/fxfa/parser/cxfa_treelist.cpp
new file mode 100644
index 0000000..520818c
--- /dev/null
+++ b/xfa/fxfa/parser/cxfa_treelist.cpp
@@ -0,0 +1,35 @@
+// 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 "xfa/fxfa/parser/cxfa_treelist.h"
+
+#include <memory>
+
+#include "core/fxcrt/fx_extension.h"
+#include "fxjs/cfxjse_engine.h"
+#include "fxjs/xfa/cjx_treelist.h"
+#include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_list.h"
+#include "xfa/fxfa/parser/cxfa_node.h"
+
+CXFA_TreeList::CXFA_TreeList(CXFA_Document* pDocument)
+    : CXFA_List(pDocument, pdfium::MakeUnique<CJX_TreeList>(this)) {
+  m_pDocument->GetScriptContext()->AddToCacheList(
+      std::unique_ptr<CXFA_TreeList>(this));
+}
+
+CXFA_TreeList::~CXFA_TreeList() {}
+
+CXFA_Node* CXFA_TreeList::NamedItem(const WideStringView& wsName) {
+  uint32_t dwHashCode = FX_HashCode_GetW(wsName, false);
+  int32_t iCount = GetLength();
+  for (int32_t i = 0; i < iCount; i++) {
+    CXFA_Node* ret = Item(i);
+    if (dwHashCode == ret->GetNameHash())
+      return ret;
+  }
+  return nullptr;
+}
diff --git a/xfa/fxfa/parser/cxfa_treelist.h b/xfa/fxfa/parser/cxfa_treelist.h
new file mode 100644
index 0000000..890fc89
--- /dev/null
+++ b/xfa/fxfa/parser/cxfa_treelist.h
@@ -0,0 +1,26 @@
+// 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
+
+#ifndef XFA_FXFA_PARSER_CXFA_TREELIST_H_
+#define XFA_FXFA_PARSER_CXFA_TREELIST_H_
+
+#include "fxjs/xfa/cjx_treelist.h"
+#include "xfa/fxfa/fxfa_basic.h"
+#include "xfa/fxfa/parser/cxfa_list.h"
+
+class CXFA_Node;
+
+class CXFA_TreeList : public CXFA_List {
+ public:
+  explicit CXFA_TreeList(CXFA_Document* pDocument);
+  ~CXFA_TreeList() override;
+
+  CJX_TreeList* JSNodeList() { return static_cast<CJX_TreeList*>(JSObject()); }
+
+  CXFA_Node* NamedItem(const WideStringView& wsName);
+};
+
+#endif  // XFA_FXFA_PARSER_CXFA_TREELIST_H_
diff --git a/xfa/fxfa/parser/cxfa_update.cpp b/xfa/fxfa/parser/cxfa_update.cpp
index f9f9d1c..8c5f6b4 100644
--- a/xfa/fxfa/parser/cxfa_update.cpp
+++ b/xfa/fxfa/parser/cxfa_update.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_update.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::Update,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Update::~CXFA_Update() {}
diff --git a/xfa/fxfa/parser/cxfa_uri.cpp b/xfa/fxfa/parser/cxfa_uri.cpp
index 6cdffce..2732ea6 100644
--- a/xfa/fxfa/parser/cxfa_uri.cpp
+++ b/xfa/fxfa/parser/cxfa_uri.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_uri.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -29,6 +32,7 @@
                 XFA_Element::Uri,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_Uri::~CXFA_Uri() {}
diff --git a/xfa/fxfa/parser/cxfa_user.cpp b/xfa/fxfa/parser/cxfa_user.cpp
index b8a7bda..7a31c4b 100644
--- a/xfa/fxfa/parser/cxfa_user.cpp
+++ b/xfa/fxfa/parser/cxfa_user.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_user.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::User,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_User::~CXFA_User() {}
diff --git a/xfa/fxfa/parser/cxfa_variables.cpp b/xfa/fxfa/parser/cxfa_variables.cpp
index 1942fb2..157c294 100644
--- a/xfa/fxfa/parser/cxfa_variables.cpp
+++ b/xfa/fxfa/parser/cxfa_variables.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_variables.h"
 
+#include "fxjs/xfa/cjx_container.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -26,6 +29,7 @@
                 XFA_Element::Variables,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Container>(this)) {}
 
 CXFA_Variables::~CXFA_Variables() {}
diff --git a/xfa/fxfa/parser/cxfa_wsdladdress.cpp b/xfa/fxfa/parser/cxfa_wsdladdress.cpp
index 94707bc..2a27cbf 100644
--- a/xfa/fxfa/parser/cxfa_wsdladdress.cpp
+++ b/xfa/fxfa/parser/cxfa_wsdladdress.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_wsdladdress.h"
 
+#include "fxjs/xfa/cjx_textnode.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -27,6 +30,7 @@
                 XFA_Element::WsdlAddress,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_TextNode>(this)) {}
 
 CXFA_WsdlAddress::~CXFA_WsdlAddress() {}
diff --git a/xfa/fxfa/parser/cxfa_wsdlconnection.cpp b/xfa/fxfa/parser/cxfa_wsdlconnection.cpp
index 4c68a7c..6159f49 100644
--- a/xfa/fxfa/parser/cxfa_wsdlconnection.cpp
+++ b/xfa/fxfa/parser/cxfa_wsdlconnection.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_wsdlconnection.h"
 
+#include "fxjs/xfa/cjx_wsdlconnection.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::PropertyData kPropertyData[] = {
@@ -34,6 +37,7 @@
                 XFA_Element::WsdlConnection,
                 kPropertyData,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_WsdlConnection>(this)) {}
 
 CXFA_WsdlConnection::~CXFA_WsdlConnection() {}
diff --git a/xfa/fxfa/parser/cxfa_xfa.cpp b/xfa/fxfa/parser/cxfa_xfa.cpp
index cd7f0ce..0865829 100644
--- a/xfa/fxfa/parser/cxfa_xfa.cpp
+++ b/xfa/fxfa/parser/cxfa_xfa.cpp
@@ -6,6 +6,9 @@
 
 #include "xfa/fxfa/parser/cxfa_xfa.h"
 
+#include "fxjs/xfa/cjx_model.h"
+#include "third_party/base/ptr_util.h"
+
 namespace {
 
 const CXFA_Node::AttributeData kAttributeData[] = {
@@ -25,6 +28,7 @@
                 XFA_Element::Xfa,
                 nullptr,
                 kAttributeData,
-                kName) {}
+                kName,
+                pdfium::MakeUnique<CJX_Model>(this)) {}
 
 CXFA_Xfa::~CXFA_Xfa() {}
diff --git a/xfa/fxfa/parser/xfa_basic_data.h b/xfa/fxfa/parser/xfa_basic_data.h
index 02fbc99..b394d35 100644
--- a/xfa/fxfa/parser/xfa_basic_data.h
+++ b/xfa/fxfa/parser/xfa_basic_data.h
@@ -17,9 +17,6 @@
 extern const XFA_SCRIPTHIERARCHY g_XFAScriptIndex[];
 extern const int32_t g_iScriptIndexCount;
 
-extern const XFA_METHODINFO g_SomMethodData[];
-extern const int32_t g_iSomMethodCount;
-
 extern const XFA_SCRIPTATTRIBUTEINFO g_SomAttributeData[];
 extern const int32_t g_iSomAttributeCount;
 
diff --git a/xfa/fxfa/parser/xfa_basic_data_element_script.cpp b/xfa/fxfa/parser/xfa_basic_data_element_script.cpp
index 112db1e..865bf8d 100644
--- a/xfa/fxfa/parser/xfa_basic_data_element_script.cpp
+++ b/xfa/fxfa/parser/xfa_basic_data_element_script.cpp
@@ -12,381 +12,97 @@
 #include "fxjs/cjx_layoutpseudomodel.h"
 #include "fxjs/cjx_logpseudomodel.h"
 #include "fxjs/cjx_node.h"
-#include "fxjs/cjx_nodelist.h"
 #include "fxjs/cjx_signaturepseudomodel.h"
+#include "fxjs/xfa/cjx_tree.h"
+#include "fxjs/xfa/cjx_treelist.h"
 #include "xfa/fxfa/fxfa_basic.h"
 
 const XFA_SCRIPTHIERARCHY g_XFAScriptIndex[] = {
-    {0, 0, 0, 2, 316},      {0, 0, 2, 2, 316},       {0, 0, 4, 2, 316},
-    {0, 0, 6, 8, 316},      {0, 0, 14, 4, 316},      {0, 0, 18, 5, 317},
-    {0, 0, 23, 2, 316},     {0, 0, 25, 1, 316},      {0, 0, 26, 12, 316},
-    {0, 0, 38, 2, 316},     {0, 0, 40, 1, 316},      {0, 0, 41, 3, 316},
-    {0, 0, 44, 2, 316},     {0, 0, 46, 6, 316},      {0, 0, 52, 0, 316},
-    {0, 0, 52, 2, 319},     {0, 0, 54, 2, 316},      {0, 0, 56, 6, 316},
-    {0, 0, 62, 0, 316},     {0, 0, 62, 0, 316},      {0, 0, 62, 2, 316},
-    {0, 0, 64, 2, 316},     {0, 0, 66, 6, 316},      {0, 0, 72, 4, 316},
-    {0, 0, 76, 7, 316},     {0, 0, 83, 2, 320},      {0, 0, 85, 3, 316},
-    {0, 0, 88, 3, 316},     {0, 0, 91, 2, 320},      {0, 0, 93, 6, 320},
-    {0, 0, 99, 4, 316},     {0, 0, 103, 2, 316},     {0, 0, 105, 3, 319},
-    {0, 0, 108, 4, 316},    {0, 0, 112, 3, 316},     {0, 0, 115, 2, 316},
-    {0, 0, 117, 6, 316},    {0, 0, 123, 12, 316},    {0, 0, 135, 2, 316},
-    {0, 0, 137, 5, 316},    {0, 0, 142, 2, 316},     {0, 0, 144, 3, 316},
-    {0, 0, 147, 1, 316},    {0, 0, 148, 14, 316},    {0, 0, 162, 2, 316},
-    {0, 0, 164, 2, 316},    {0, 0, 166, 3, 316},     {0, 0, 169, 2, 316},
-    {0, 0, 171, 2, 316},    {0, 0, 173, 2, 316},     {0, 0, 175, 4, 316},
-    {0, 0, 179, 2, 316},    {0, 0, 181, 2, 316},     {0, 0, 183, 0, 319},
-    {0, 0, 183, 20, 316},   {0, 0, 203, 1, 316},     {0, 0, 204, 3, 316},
-    {0, 0, 207, 2, 316},    {0, 0, 209, 0, 316},     {0, 0, 209, 2, 316},
-    {0, 0, 211, 2, 316},    {0, 0, 213, 4, 320},     {0, 0, 217, 0, 316},
-    {0, 0, 217, 1, 316},    {0, 0, 218, 3, 316},     {0, 4, 221, 0, 312},
-    {4, 1, 221, 1, 316},    {5, 0, 222, 2, 316},     {5, 1, 224, 3, -1},
-    {6, 0, 227, 0, 316},    {6, 0, 227, 2, 316},     {6, 0, 229, 2, 316},
-    {6, 0, 231, 3, 316},    {6, 0, 234, 2, 316},     {6, 0, 236, 6, 316},
-    {6, 0, 242, 10, 317},   {6, 0, 252, 9, 316},     {6, 0, 261, 5, 318},
-    {6, 0, 266, 4, 318},    {6, 0, 270, 2, 316},     {6, 0, 272, 2, 316},
-    {6, 0, 274, 5, 316},    {6, 0, 279, 3, 316},     {6, 0, 282, 2, 316},
-    {6, 0, 284, 2, 316},    {6, 0, 286, 2, 316},     {6, 0, 288, 2, 316},
-    {6, 0, 290, 4, 316},    {6, 0, 294, 3, 316},     {6, 0, 297, 3, 316},
-    {6, 0, 300, 2, 316},    {6, 0, 302, 2, 316},     {6, 0, 304, 2, 316},
-    {6, 13, 306, 36, 317},  {19, 0, 342, 3, 316},    {19, 0, 345, 2, 316},
-    {19, 0, 347, 2, 316},   {19, 0, 349, 2, 316},    {19, 0, 351, 7, 317},
-    {19, 2, 358, 16, 312},  {21, 0, 374, 2, 320},    {21, 0, 376, 2, 316},
-    {21, 0, 378, 0, 316},   {21, 0, 378, 2, 316},    {21, 0, 380, 6, 316},
-    {21, 0, 386, 3, 316},   {21, 0, 389, 2, 316},    {21, 0, 391, 4, 316},
-    {21, 0, 395, 0, 316},   {21, 5, 395, 30, 316},   {26, 0, 425, 2, 320},
-    {26, 0, 427, 3, 316},   {26, 0, 430, 2, 320},    {26, 0, 432, 5, 316},
-    {26, 0, 437, 2, 316},   {26, 0, 439, 3, 316},    {26, 0, 442, 2, 316},
-    {26, 0, 444, 8, 316},   {26, 0, 452, 1, 316},    {26, 0, 453, 2, 316},
-    {26, 0, 455, 2, 316},   {26, 0, 457, 4, 316},    {26, 0, 461, 0, 316},
-    {26, 0, 461, 2, 316},   {26, 0, 463, 2, 316},    {26, 0, 465, 6, 318},
-    {26, 5, 471, 31, 317},  {31, 0, 502, 2, 320},    {31, 0, 504, 2, 316},
-    {31, 0, 506, 2, 316},   {31, 0, 508, 4, 320},    {31, 16, 512, 11, 312},
-    {47, 0, 523, 2, 316},   {47, 0, 525, 2, 316},    {47, 0, 527, 2, 316},
-    {47, 0, 529, 2, 316},   {47, 0, 531, 3, 316},    {47, 0, 534, 2, 316},
-    {47, 0, 536, 3, 316},   {47, 0, 539, 3, 316},    {47, 0, 542, 4, 318},
-    {47, 0, 546, 4, 316},   {47, 0, 550, 2, 316},    {47, 0, 552, 0, 316},
-    {47, 0, 552, 2, 316},   {47, 0, 554, 3, 316},    {47, 0, 557, 6, 316},
-    {47, 0, 563, 2, 316},   {47, 0, 565, 2, 316},    {47, 0, 567, 3, 316},
-    {47, 19, 570, 1, 312},  {66, 0, 571, 2, 316},    {66, 0, 573, 8, 316},
-    {66, 0, 581, 2, 316},   {66, 0, 583, 4, 316},    {66, 0, 587, 5, 316},
-    {66, 0, 592, 3, 316},   {66, 0, 595, 2, 320},    {66, 0, 597, 3, 316},
-    {66, 0, 600, 7, 316},   {66, 0, 607, 3, 316},    {66, 0, 610, 0, 316},
-    {66, 0, 610, 4, 317},   {66, 0, 614, 4, 318},    {66, 0, 618, 2, 320},
-    {66, 0, 620, 5, 316},   {66, 0, 625, 2, 316},    {66, 0, 627, 2, 316},
-    {66, 0, 629, 2, 320},   {66, 0, 631, 2, 320},    {66, 0, 633, 4, 316},
-    {66, 0, 637, 2, 316},   {66, 0, 639, 1, 316},    {66, 0, 640, 1, 316},
-    {66, 0, 641, 4, 316},   {66, 0, 645, 3, 316},    {66, 7, 648, 2, 319},
-    {73, 0, 650, 2, 316},   {73, 0, 652, 2, 316},    {73, 0, 654, 3, 316},
-    {73, 4, 657, 4, 312},   {77, 0, 661, 10, 316},   {77, 0, 671, 2, 316},
-    {77, 0, 673, 4, 316},   {77, 0, 677, 4, 316},    {77, 0, 681, 3, 316},
-    {77, 0, 684, 2, 316},   {77, 0, 686, 2, 316},    {77, 0, 688, 8, 317},
-    {77, 0, 696, 3, 316},   {77, 0, 699, 3, 316},    {77, 0, 702, 2, 316},
-    {77, 0, 704, 2, 316},   {77, 0, 706, 5, 316},    {77, 0, 711, 4, 316},
-    {77, 0, 715, 2, 316},   {77, 0, 717, 8, 318},    {77, 0, 725, 1, 316},
-    {77, 0, 726, 2, 320},   {77, 0, 728, 3, 316},    {77, 1, 731, 4, 316},
-    {78, 0, 735, 5, 316},   {78, 0, 740, 3, 316},    {78, 0, 743, 1, 316},
-    {78, 0, 744, 2, 320},   {78, 0, 746, 0, 313},    {78, 0, 746, 2, 316},
-    {78, 5, 748, 3, 316},   {83, 0, 751, 5, 316},    {83, 0, 756, 7, 316},
-    {83, 0, 763, 6, 316},   {83, 0, 769, 3, 316},    {83, 0, 772, 2, 316},
-    {83, 0, 774, 5, 316},   {83, 0, 779, 2, 316},    {83, 0, 781, 0, 314},
-    {83, 0, 781, 2, 316},   {83, 0, 783, 1, 316},    {83, 0, 784, 2, 316},
-    {83, 0, 786, 5, 316},   {83, 0, 791, 2, 316},    {83, 0, 793, 1, 316},
-    {83, 0, 794, 2, 316},   {83, 0, 796, 2, 316},    {83, 0, 798, 6, 316},
-    {83, 0, 804, 2, 316},   {83, 0, 806, 2, 320},    {83, 0, 808, 3, 316},
-    {83, 0, 811, 4, 316},   {83, 0, 815, 2, 316},    {83, 0, 817, 2, 316},
-    {83, 0, 819, 2, 316},   {83, 0, 821, 2, 316},    {83, 0, 823, 2, 316},
-    {83, 0, 825, 2, 316},   {83, 0, 827, 4, 318},    {83, 1, 831, 2, 316},
-    {84, 0, 833, 5, 316},   {84, 0, 838, 20, 317},   {84, 0, 858, 2, 316},
-    {84, 0, 860, 0, 316},   {84, 0, 860, 2, 316},    {84, 0, 862, 4, 320},
-    {84, 0, 866, 0, 316},   {84, 0, 866, 2, 316},    {84, 0, 868, 1, 316},
-    {84, 0, 869, 2, 316},   {84, 0, 871, 3, 316},    {84, 0, 874, 2, 316},
-    {84, 0, 876, 2, 316},   {84, 0, 878, 4, 316},    {84, 0, 882, 3, 316},
-    {84, 0, 885, 17, 316},  {84, 6, 902, 1, 319},    {90, 0, 903, 2, 316},
-    {90, 0, 905, 2, 320},   {90, 0, 907, 2, 320},    {90, 0, 909, 2, 316},
-    {90, 0, 911, 2, 316},   {90, 0, 913, 4, 318},    {90, 0, 917, 2, 316},
-    {90, 5, 919, 0, 312},   {95, 0, 919, 2, 316},    {95, 0, 921, 4, 316},
-    {95, 0, 925, 4, 316},   {95, 0, 929, 6, 316},    {95, 0, 935, 2, 316},
-    {95, 0, 937, 4, 316},   {95, 0, 941, 3, 316},    {95, 0, 944, 3, 316},
-    {95, 0, 947, 2, 316},   {95, 0, 949, 3, 316},    {95, 0, 952, 0, 316},
-    {95, 0, 952, 0, 316},   {95, 0, 952, 2, 316},    {95, 0, 954, 7, 316},
-    {95, 0, 961, 2, 316},   {95, 0, 963, 0, 319},    {95, 0, 963, 7, 316},
-    {95, 0, 970, 2, 316},   {95, 0, 972, 2, 316},    {95, 3, 974, 1, 316},
-    {98, 0, 975, 2, 320},   {98, 0, 977, 4, 316},    {98, 0, 981, 0, 316},
-    {98, 0, 981, 2, 316},   {98, 0, 983, 2, 316},    {98, 0, 985, 4, 316},
-    {98, 0, 989, 1, 316},   {98, 0, 990, 2, 316},    {98, 0, 992, 2, 316},
-    {98, 0, 994, 3, 316},   {98, 0, 997, 2, 317},    {98, 0, 999, 0, 316},
-    {98, 0, 999, 4, 316},   {98, 0, 1003, 4, 316},   {98, 0, 1007, 2, 316},
-    {98, 0, 1009, 3, 316},  {98, 0, 1012, 4, 316},   {98, 0, 1016, 7, 316},
-    {98, 0, 1023, 4, 316},  {98, 0, 1027, 1, 313},   {98, 17, 1028, 3, 316},
-    {115, 0, 1031, 5, 316}, {115, 0, 1036, 2, 316},  {115, 0, 1038, 1, 316},
-    {115, 0, 1039, 4, 316}, {115, 0, 1043, 2, 316},  {115, 0, 1045, 2, 316},
-    {115, 0, 1047, 1, 316}, {115, 0, 1048, 2, 316},  {115, 0, 1050, 5, 316},
-    {115, 0, 1055, 1, -1},  {115, 4, 1056, 1, 312},  {119, 1, 1057, 0, 313},
-    {120, 2, 1057, 8, 312}, {122, 11, 1065, 6, 315}, {133, 2, 1071, 0, 316},
-    {135, 0, 1071, 0, 316}, {135, 3, 1071, 2, 316},  {138, 0, 1073, 2, 316},
+    {0, 2, 316},    {2, 2, 316},    {4, 2, 316},    {6, 8, 316},
+    {14, 4, 316},   {18, 5, 317},   {23, 2, 316},   {25, 1, 316},
+    {26, 12, 316},  {38, 2, 316},   {40, 1, 316},   {41, 3, 316},
+    {44, 2, 316},   {46, 6, 316},   {52, 0, 316},   {52, 2, 319},
+    {54, 2, 316},   {56, 6, 316},   {62, 0, 316},   {62, 0, 316},
+    {62, 2, 316},   {64, 2, 316},   {66, 6, 316},   {72, 4, 316},
+    {76, 7, 316},   {83, 2, 320},   {85, 3, 316},   {88, 3, 316},
+    {91, 2, 320},   {93, 6, 320},   {99, 4, 316},   {103, 2, 316},
+    {105, 3, 319},  {108, 4, 316},  {112, 3, 316},  {115, 2, 316},
+    {117, 6, 316},  {123, 12, 316}, {135, 2, 316},  {137, 5, 316},
+    {142, 2, 316},  {144, 3, 316},  {147, 1, 316},  {148, 14, 316},
+    {162, 2, 316},  {164, 2, 316},  {166, 3, 316},  {169, 2, 316},
+    {171, 2, 316},  {173, 2, 316},  {175, 4, 316},  {179, 2, 316},
+    {181, 2, 316},  {183, 0, 319},  {183, 20, 316}, {203, 1, 316},
+    {204, 3, 316},  {207, 2, 316},  {209, 0, 316},  {209, 2, 316},
+    {211, 2, 316},  {213, 4, 320},  {217, 0, 316},  {217, 1, 316},
+    {218, 3, 316},  {221, 0, 312},  {221, 1, 316},  {222, 2, 316},
+    {224, 3, -1},   {227, 0, 316},  {227, 2, 316},  {229, 2, 316},
+    {231, 3, 316},  {234, 2, 316},  {236, 6, 316},  {242, 10, 317},
+    {252, 9, 316},  {261, 5, 318},  {266, 4, 318},  {270, 2, 316},
+    {272, 2, 316},  {274, 5, 316},  {279, 3, 316},  {282, 2, 316},
+    {284, 2, 316},  {286, 2, 316},  {288, 2, 316},  {290, 4, 316},
+    {294, 3, 316},  {297, 3, 316},  {300, 2, 316},  {302, 2, 316},
+    {304, 2, 316},  {306, 36, 317}, {342, 3, 316},  {345, 2, 316},
+    {347, 2, 316},  {349, 2, 316},  {351, 7, 317},  {358, 16, 312},
+    {374, 2, 320},  {376, 2, 316},  {378, 0, 316},  {378, 2, 316},
+    {380, 6, 316},  {386, 3, 316},  {389, 2, 316},  {391, 4, 316},
+    {395, 0, 316},  {395, 30, 316}, {425, 2, 320},  {427, 3, 316},
+    {430, 2, 320},  {432, 5, 316},  {437, 2, 316},  {439, 3, 316},
+    {442, 2, 316},  {444, 8, 316},  {452, 1, 316},  {453, 2, 316},
+    {455, 2, 316},  {457, 4, 316},  {461, 0, 316},  {461, 2, 316},
+    {463, 2, 316},  {465, 6, 318},  {471, 31, 317}, {502, 2, 320},
+    {504, 2, 316},  {506, 2, 316},  {508, 4, 320},  {512, 11, 312},
+    {523, 2, 316},  {525, 2, 316},  {527, 2, 316},  {529, 2, 316},
+    {531, 3, 316},  {534, 2, 316},  {536, 3, 316},  {539, 3, 316},
+    {542, 4, 318},  {546, 4, 316},  {550, 2, 316},  {552, 0, 316},
+    {552, 2, 316},  {554, 3, 316},  {557, 6, 316},  {563, 2, 316},
+    {565, 2, 316},  {567, 3, 316},  {570, 1, 312},  {571, 2, 316},
+    {573, 8, 316},  {581, 2, 316},  {583, 4, 316},  {587, 5, 316},
+    {592, 3, 316},  {595, 2, 320},  {597, 3, 316},  {600, 7, 316},
+    {607, 3, 316},  {610, 0, 316},  {610, 4, 317},  {614, 4, 318},
+    {618, 2, 320},  {620, 5, 316},  {625, 2, 316},  {627, 2, 316},
+    {629, 2, 320},  {631, 2, 320},  {633, 4, 316},  {637, 2, 316},
+    {639, 1, 316},  {640, 1, 316},  {641, 4, 316},  {645, 3, 316},
+    {648, 2, 319},  {650, 2, 316},  {652, 2, 316},  {654, 3, 316},
+    {657, 4, 312},  {661, 10, 316}, {671, 2, 316},  {673, 4, 316},
+    {677, 4, 316},  {681, 3, 316},  {684, 2, 316},  {686, 2, 316},
+    {688, 8, 317},  {696, 3, 316},  {699, 3, 316},  {702, 2, 316},
+    {704, 2, 316},  {706, 5, 316},  {711, 4, 316},  {715, 2, 316},
+    {717, 8, 318},  {725, 1, 316},  {726, 2, 320},  {728, 3, 316},
+    {731, 4, 316},  {735, 5, 316},  {740, 3, 316},  {743, 1, 316},
+    {744, 2, 320},  {746, 0, 313},  {746, 2, 316},  {748, 3, 316},
+    {751, 5, 316},  {756, 7, 316},  {763, 6, 316},  {769, 3, 316},
+    {772, 2, 316},  {774, 5, 316},  {779, 2, 316},  {781, 0, 314},
+    {781, 2, 316},  {783, 1, 316},  {784, 2, 316},  {786, 5, 316},
+    {791, 2, 316},  {793, 1, 316},  {794, 2, 316},  {796, 2, 316},
+    {798, 6, 316},  {804, 2, 316},  {806, 2, 320},  {808, 3, 316},
+    {811, 4, 316},  {815, 2, 316},  {817, 2, 316},  {819, 2, 316},
+    {821, 2, 316},  {823, 2, 316},  {825, 2, 316},  {827, 4, 318},
+    {831, 2, 316},  {833, 5, 316},  {838, 20, 317}, {858, 2, 316},
+    {860, 0, 316},  {860, 2, 316},  {862, 4, 320},  {866, 0, 316},
+    {866, 2, 316},  {868, 1, 316},  {869, 2, 316},  {871, 3, 316},
+    {874, 2, 316},  {876, 2, 316},  {878, 4, 316},  {882, 3, 316},
+    {885, 17, 316}, {902, 1, 319},  {903, 2, 316},  {905, 2, 320},
+    {907, 2, 320},  {909, 2, 316},  {911, 2, 316},  {913, 4, 318},
+    {917, 2, 316},  {919, 0, 312},  {919, 2, 316},  {921, 4, 316},
+    {925, 4, 316},  {929, 6, 316},  {935, 2, 316},  {937, 4, 316},
+    {941, 3, 316},  {944, 3, 316},  {947, 2, 316},  {949, 3, 316},
+    {952, 0, 316},  {952, 0, 316},  {952, 2, 316},  {954, 7, 316},
+    {961, 2, 316},  {963, 0, 319},  {963, 7, 316},  {970, 2, 316},
+    {972, 2, 316},  {974, 1, 316},  {975, 2, 320},  {977, 4, 316},
+    {981, 0, 316},  {981, 2, 316},  {983, 2, 316},  {985, 4, 316},
+    {989, 1, 316},  {990, 2, 316},  {992, 2, 316},  {994, 3, 316},
+    {997, 2, 317},  {999, 0, 316},  {999, 4, 316},  {1003, 4, 316},
+    {1007, 2, 316}, {1009, 3, 316}, {1012, 4, 316}, {1016, 7, 316},
+    {1023, 4, 316}, {1027, 1, 313}, {1028, 3, 316}, {1031, 5, 316},
+    {1036, 2, 316}, {1038, 1, 316}, {1039, 4, 316}, {1043, 2, 316},
+    {1045, 2, 316}, {1047, 1, 316}, {1048, 2, 316}, {1050, 5, 316},
+    {1055, 1, -1},  {1056, 1, 312}, {1057, 0, 313}, {1057, 8, 312},
+    {1065, 6, 315}, {1071, 0, 316}, {1071, 0, 316}, {1071, 2, 316},
+    {1073, 2, 316},
 };
 const int32_t g_iScriptIndexCount =
     sizeof(g_XFAScriptIndex) / sizeof(XFA_SCRIPTHIERARCHY);
 
-const XFA_METHODINFO g_SomMethodData[] = {
-    {0x3c752495, L"verify",
-     (XFA_METHOD_CALLBACK)&CJX_SignaturePseudoModel::Verify},
-    {0xa68635f1, L"sign", (XFA_METHOD_CALLBACK)&CJX_SignaturePseudoModel::Sign},
-    {0xa7f2c5e6, L"enumerate",
-     (XFA_METHOD_CALLBACK)&CJX_SignaturePseudoModel::Enumerate},
-    {0xd8ed1467, L"clear",
-     (XFA_METHOD_CALLBACK)&CJX_SignaturePseudoModel::Clear},
-    {0x4bdcce13, L"execute",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_WsdlConnection_Execute},
-    {0x1c296ba4, L"restore",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Delta_Restore},
-    {0x7d123a9, L"clearItems",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_ClearItems},
-    {0xfb0b007, L"execEvent",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_ExecEvent},
-    {0x6716ce97, L"execInitialize",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_ExecInitialize},
-    {0x7bb919c2, L"deleteItem",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_DeleteItem},
-    {0x9f053d5e, L"getSaveItem",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_GetSaveItem},
-    {0xbbd32747, L"boundItem",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_BoundItem},
-    {0xc492d950, L"getItemState",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_GetItemState},
-    {0xc6013cd3, L"execCalculate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_ExecCalculate},
-    {0xd8930d0e, L"setItems",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_SetItems},
-    {0xe0f15045, L"getDisplayItem",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_GetDisplayItem},
-    {0xe23acddc, L"setItemState",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_SetItemState},
-    {0xe2dfb2f8, L"addItem",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_AddItem},
-    {0xef8ce48f, L"execValidate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Field_ExecValidate},
-    {0x461079ef, L"emit", (XFA_METHOD_CALLBACK)&CJX_EventPseudoModel::Emit},
-    {0xfec90c63, L"reset", (XFA_METHOD_CALLBACK)&CJX_EventPseudoModel::Reset},
-    {0xfb0b007, L"execEvent",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ExclGroup_ExecEvent},
-    {0x3d832221, L"selectedMember",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ExclGroup_SelectedMember},
-    {0x6716ce97, L"execInitialize",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ExclGroup_ExecInitialize},
-    {0xc6013cd3, L"execCalculate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ExclGroup_ExecCalculate},
-    {0xef8ce48f, L"execValidate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ExclGroup_ExecValidate},
-    {0xfb0b007, L"execEvent",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Subform_ExecEvent},
-    {0x6716ce97, L"execInitialize",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Subform_ExecInitialize},
-    {0xc6013cd3, L"execCalculate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Subform_ExecCalculate},
-    {0xd9b9b1f1, L"getInvalidObjects",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Subform_GetInvalidObjects},
-    {0xef8ce48f, L"execValidate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Subform_ExecValidate},
-    {0xa366b7c, L"exportData",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::ExportData},
-    {0x16cc226c, L"gotoURL",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::GotoURL},
-    {0x1e0722f5, L"pageDown",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::PageDown},
-    {0x3e66cb2c, L"setFocus",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::SetFocus},
-    {0x4ac9faae, L"openList",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::OpenList},
-    {0x7b89714f, L"response",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::Response},
-    {0x7fd9fd58, L"documentInBatch",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::DocumentInBatch},
-    {0xaf1d019d, L"resetData",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::ResetData},
-    {0xb07be13c, L"beep", (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::Beep},
-    {0xb1882ca0, L"getFocus",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::GetFocus},
-    {0xbf4ba9ee, L"messageBox",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::MessageBox},
-    {0xd6d4dbc1, L"documentCountInBatch",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::DocumentCountInBatch},
-    {0xdd7676ed, L"print", (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::Print},
-    {0xe2f863d0, L"currentDateTime",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::CurrentDateTime},
-    {0xf995d0f5, L"importData",
-     (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::ImportData},
-    {0xfeb96b62, L"pageUp", (XFA_METHOD_CALLBACK)&CJX_HostPseudoModel::PageUp},
-    {0x68, L"h", (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::H},
-    {0x77, L"w", (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::W},
-    {0x78, L"x", (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::X},
-    {0x79, L"y", (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::Y},
-    {0x5460206, L"pageCount",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::PageCount},
-    {0x5eb5b0f, L"pageSpan",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::PageSpan},
-    {0x10f1b1bd, L"page", (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::Page},
-    {0x1c1e6318, L"pageContent",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::PageContent},
-    {0x1c1f4a5c, L"absPageCount",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::AbsPageCount},
-    {0x1ec47db5, L"absPageCountInBatch",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::AbsPageCountInBatch},
-    {0x2e4ecbdb, L"sheetCountInBatch",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::SheetCountInBatch},
-    {0x2fcff4b5, L"relayout",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::Relayout},
-    {0x3bf1c2a5, L"absPageSpan",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::AbsPageSpan},
-    {0x5775c2cc, L"absPageInBatch",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::AbsPageInBatch},
-    {0x8c5feb32, L"sheetInBatch",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::SheetInBatch},
-    {0x8f3a8379, L"sheet", (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::Sheet},
-    {0x96f3c4cb, L"relayoutPageArea",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::RelayoutPageArea},
-    {0xd2a4a542, L"sheetCount",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::SheetCount},
-    {0xe74f0653, L"absPage",
-     (XFA_METHOD_CALLBACK)&CJX_LayoutPseudoModel::AbsPage},
-    {0x44c352ad, L"formNodes",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Template_FormNodes},
-    {0x45efb847, L"remerge",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Template_Remerge},
-    {0x6716ce97, L"execInitialize",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Template_ExecInitialize},
-    {0x712c6afa, L"createNode",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Template_CreateNode},
-    {0xa8a35e25, L"recalculate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Template_Recalculate},
-    {0xc6013cd3, L"execCalculate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Template_ExecCalculate},
-    {0xef8ce48f, L"execValidate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Template_ExecValidate},
-    {0x4cc1c0f9, L"moveCurrentRecord",
-     (XFA_METHOD_CALLBACK)&CJX_DataWindow::MoveCurrentRecord},
-    {0x5779d65f, L"record", (XFA_METHOD_CALLBACK)&CJX_DataWindow::Record},
-    {0x8a476498, L"gotoRecord",
-     (XFA_METHOD_CALLBACK)&CJX_DataWindow::GotoRecord},
-    {0xaac241c8, L"isRecordGroup",
-     (XFA_METHOD_CALLBACK)&CJX_DataWindow::IsRecordGroup},
-    {0x1c6f4277, L"evaluate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Manifest_Evaluate},
-    {0x2afec2cc, L"moveInstance",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_InstanceManager_MoveInstance},
-    {0x2bf94a63, L"removeInstance",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_InstanceManager_RemoveInstance},
-    {0x303adaf4, L"setInstances",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_InstanceManager_SetInstances},
-    {0x4d76b89e, L"addInstance",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_InstanceManager_AddInstance},
-    {0xc660dc8a, L"insertInstance",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_InstanceManager_InsertInstance},
-    {0xddfd1ea1, L"metadata",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Desc_Metadata},
-    {0x44c352ad, L"formNodes",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Form_FormNodes},
-    {0x45efb847, L"remerge",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Form_Remerge},
-    {0x6716ce97, L"execInitialize",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Form_ExecInitialize},
-    {0xa8a35e25, L"recalculate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Form_Recalculate},
-    {0xc6013cd3, L"execCalculate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Form_ExecCalculate},
-    {0xef8ce48f, L"execValidate",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Form_ExecValidate},
-    {0x60490a85, L"message", (XFA_METHOD_CALLBACK)&CJX_LogPseudoModel::Message},
-    {0x60ecfcc9, L"traceDeactivate",
-     (XFA_METHOD_CALLBACK)&CJX_LogPseudoModel::TraceDeactivate},
-    {0x86a0f4c0, L"traceActivate",
-     (XFA_METHOD_CALLBACK)&CJX_LogPseudoModel::TraceActivate},
-    {0x93eac39a, L"traceEnabled",
-     (XFA_METHOD_CALLBACK)&CJX_LogPseudoModel::TraceEnabled},
-    {0xd1227e6f, L"trace", (XFA_METHOD_CALLBACK)&CJX_LogPseudoModel::Trace},
-    {0x36c0ee14, L"getAttribute",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Packet_GetAttribute},
-    {0x5468e2a0, L"setAttribute",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Packet_SetAttribute},
-    {0xadc48de2, L"removeAttribute",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Packet_RemoveAttribute},
-    {0x3848b3f, L"next", (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Next},
-    {0x14e25bc8, L"cancelBatch",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_CancelBatch},
-    {0x3ce05d68, L"first", (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_First},
-    {0x649e1e65, L"updateBatch",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_UpdateBatch},
-    {0x6a3405dd, L"previous",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Previous},
-    {0x74818fb3, L"isBOF", (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_IsBOF},
-    {0x74d07a76, L"isEOF", (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_IsEOF},
-    {0x7613cb66, L"cancel",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Cancel},
-    {0x7baca2e3, L"update",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Update},
-    {0x8b90e1f2, L"open", (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Open},
-    {0x9c6471b3, L"delete",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Delete},
-    {0xa7315093, L"addNew",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_AddNew},
-    {0xa7ce5f8d, L"requery",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Requery},
-    {0xc7368674, L"resync",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Resync},
-    {0xd9f47f36, L"close", (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Close},
-    {0xf54481d4, L"last", (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_Last},
-    {0xf7965460, L"hasDataChanged",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_Source_HasDataChanged},
-    {0x6275f6af, L"item",
-     (XFA_METHOD_CALLBACK)&CJX_NodeList::Script_ListClass_Item},
-    {0x7033bfd5, L"insert",
-     (XFA_METHOD_CALLBACK)&CJX_NodeList::Script_ListClass_Insert},
-    {0x9cab7cae, L"remove",
-     (XFA_METHOD_CALLBACK)&CJX_NodeList::Script_ListClass_Remove},
-    {0xda12e518, L"append",
-     (XFA_METHOD_CALLBACK)&CJX_NodeList::Script_ListClass_Append},
-    {0xd892a054, L"namedItem",
-     (XFA_METHOD_CALLBACK)&CJX_NodeList::Script_TreelistClass_NamedItem},
-    {0xba2dd386, L"resolveNode",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_TreeClass_ResolveNode},
-    {0xe509e2b9, L"resolveNodes",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_TreeClass_ResolveNodes},
-    {0x1bca1ebd, L"applyXSL",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_ApplyXSL},
-    {0x36c0ee14, L"getAttribute",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_GetAttribute},
-    {0x5468e2a0, L"setAttribute",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_SetAttribute},
-    {0x5ee00996, L"setElement",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_SetElement},
-    {0x92dada4f, L"saveFilteredXML",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_SaveFilteredXML},
-    {0x9c456500, L"saveXML",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_SaveXML},
-    {0xabd3200a, L"getElement",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_GetElement},
-    {0xb269c60d, L"isPropertySpecified",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_IsPropertySpecified},
-    {0xb528be91, L"loadXML",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_LoadXML},
-    {0xd9f46591, L"clone",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_Clone},
-    {0xe006a76b, L"assignNode",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_NodeClass_AssignNode},
-    {0x7303fcea, L"getDelta",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ContainerClass_GetDelta},
-    {0xe7742c9d, L"getDeltas",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ContainerClass_GetDeltas},
-    {0x30ff6aad, L"clearErrorList",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ModelClass_ClearErrorList},
-    {0x712c6afa, L"createNode",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ModelClass_CreateNode},
-    {0x83a6411d, L"isCompatibleNS",
-     (XFA_METHOD_CALLBACK)&CJX_Node::Script_ModelClass_IsCompatibleNS},
-};
-const int32_t g_iSomMethodCount =
-    sizeof(g_SomMethodData) / sizeof(XFA_METHODINFO);
-
 const XFA_SCRIPTATTRIBUTEINFO g_SomAttributeData[] = {
     {0xbe52dfbf, L"desc",
      (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_Attribute_String,
@@ -3435,8 +3151,7 @@
     {0xd996fa9b, L"hand",
      (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_Attribute_String,
      XFA_Attribute::Hand, XFA_ScriptType::Basic},
-    {0xa60dd202, L"length",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_NodeList::Script_ListClass_Length,
+    {0xa60dd202, L"length", (XFA_ATTRIBUTE_CALLBACK)&CJX_List::length,
      XFA_Attribute::Unknown, XFA_ScriptType::Basic},
     {0x20146, L"db", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_Source_Db,
      XFA_Attribute::Unknown, XFA_ScriptType::Basic},
@@ -3519,32 +3234,26 @@
     {0xb2c80857, L"className",
      (XFA_ATTRIBUTE_CALLBACK)&CJX_Object::Script_ObjectClass_ClassName,
      XFA_Attribute::Unknown, XFA_ScriptType::Basic},
-    {0xa60dd202, L"length",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_NodeList::Script_ListClass_Length,
+    {0xa60dd202, L"length", (XFA_ATTRIBUTE_CALLBACK)&CJX_TreeList::length,
      XFA_Attribute::Unknown, XFA_ScriptType::Basic},
     {0x31b19c1, L"name",
      (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_Attribute_String,
      XFA_Attribute::Name, XFA_ScriptType::Basic},
-    {0x9f9d0f9, L"all", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_TreeClass_All,
+    {0x9f9d0f9, L"all", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::all,
      XFA_Attribute::Unknown, XFA_ScriptType::Object},
-    {0x4df15659, L"nodes",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_TreeClass_Nodes,
+    {0x4df15659, L"nodes", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::nodes,
      XFA_Attribute::Unknown, XFA_ScriptType::Object},
-    {0x78a8d6cf, L"classAll",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_TreeClass_ClassAll,
+    {0x78a8d6cf, L"classAll", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::classAll,
      XFA_Attribute::Unknown, XFA_ScriptType::Object},
-    {0xcad6d8ca, L"parent",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_TreeClass_Parent,
+    {0xcad6d8ca, L"parent", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::parent,
      XFA_Attribute::Unknown, XFA_ScriptType::Object},
-    {0xd5679c78, L"index",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_TreeClass_Index,
+    {0xd5679c78, L"index", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::index,
      XFA_Attribute::Unknown, XFA_ScriptType::Basic},
-    {0xdb5b4bce, L"classIndex",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_TreeClass_ClassIndex,
+    {0xdb5b4bce, L"classIndex", (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::classIndex,
      XFA_Attribute::Unknown, XFA_ScriptType::Basic},
     {0xe4989adf, L"somExpression",
-     (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_TreeClass_SomExpression,
-     XFA_Attribute::Unknown, XFA_ScriptType::Basic},
+     (XFA_ATTRIBUTE_CALLBACK)&CJX_Tree::somExpression, XFA_Attribute::Unknown,
+     XFA_ScriptType::Basic},
     {0x21aed, L"id", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_Attribute_String,
      XFA_Attribute::Id, XFA_ScriptType::Basic},
     {0x234a1, L"ns", (XFA_ATTRIBUTE_CALLBACK)&CJX_Node::Script_NodeClass_Ns,
diff --git a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp
index 868361e..405bb21 100644
--- a/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp
+++ b/xfa/fxfa/parser/xfa_document_datamerger_imp.cpp
@@ -114,7 +114,7 @@
 void CreateDataBinding(CXFA_Node* pFormNode,
                        CXFA_Node* pDataNode,
                        bool bDataToForm) {
-  pFormNode->JSNode()->SetBindingNode(pDataNode);
+  pFormNode->SetBindingNode(pDataNode);
   pDataNode->AddBindItem(pFormNode);
   XFA_Element eType = pFormNode->GetElementType();
   if (eType != XFA_Element::Field && eType != XFA_Element::ExclGroup)
@@ -1535,7 +1535,7 @@
     while (CXFA_Node* pNode = pFormRoot->GetNodeItem(XFA_NODEITEM_FirstChild))
       pFormRoot->RemoveChild(pNode, true);
 
-    pFormRoot->JSNode()->SetBindingNode(nullptr);
+    pFormRoot->SetBindingNode(nullptr);
   }
   m_rgGlobalBinding.clear();