Clear v8 object binding in CXFA_Object destructor.
Noticed this possibility while looking at another issue,
this is a best practice to ensure validity.
- Rename some functions for clarity.
- Insist on a non-null return for GetOrCreate...()
- Handle dependence in CFXA_Object destruction on the object
that owns it (and may be cleaning it up in its own destructor).
Change-Id: I129817f636455f630d9d911f6fff5022faa72e7b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52850
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/xfa/cfxjse_context.cpp b/fxjs/xfa/cfxjse_context.cpp
index 5dec89c..7a3b593 100644
--- a/fxjs/xfa/cfxjse_context.cpp
+++ b/fxjs/xfa/cfxjse_context.cpp
@@ -144,6 +144,13 @@
hObject->SetAlignedPointerInInternalField(1, lpNewBinding);
}
+void FXJSE_ClearObjectBinding(v8::Local<v8::Object> hObject) {
+ ASSERT(!hObject.IsEmpty());
+ ASSERT(hObject->InternalFieldCount() == 2);
+ hObject->SetAlignedPointerInInternalField(0, nullptr);
+ hObject->SetAlignedPointerInInternalField(1, nullptr);
+}
+
CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(
v8::Local<v8::Object> hJSObject) {
ASSERT(!hJSObject.IsEmpty());
diff --git a/fxjs/xfa/cfxjse_context.h b/fxjs/xfa/cfxjse_context.h
index 347a69d..b519e77 100644
--- a/fxjs/xfa/cfxjse_context.h
+++ b/fxjs/xfa/cfxjse_context.h
@@ -52,6 +52,7 @@
void FXJSE_UpdateObjectBinding(v8::Local<v8::Object> hObject,
CFXJSE_HostObject* lpNewBinding);
+void FXJSE_ClearObjectBinding(v8::Local<v8::Object> hJSObject);
CFXJSE_HostObject* FXJSE_RetrieveObjectBinding(v8::Local<v8::Object> hJSObject);
#endif // FXJS_XFA_CFXJSE_CONTEXT_H_
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp
index 8c20211..e4675fd 100644
--- a/fxjs/xfa/cfxjse_engine.cpp
+++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -118,6 +118,9 @@
CFXJSE_Engine::~CFXJSE_Engine() {
for (const auto& pair : m_mapVariableToContext)
delete ToThisProxy(pair.second->GetGlobalObject().get());
+
+ for (const auto& pair : m_mapObjectToValue)
+ pair.second->ClearHostObject();
}
bool CFXJSE_Engine::RunScript(CXFA_Script::Type eScriptType,
@@ -144,7 +147,8 @@
AutoRestorer<UnownedPtr<CXFA_Object>> nodeRestorer(&m_pThisObject);
m_pThisObject = pThisObject;
- CFXJSE_Value* pValue = pThisObject ? GetJSValueFromMap(pThisObject) : nullptr;
+ CFXJSE_Value* pValue =
+ pThisObject ? GetOrCreateJSBindingFromMap(pThisObject) : nullptr;
IJS_Runtime::ScopedEventContext ctx(m_pSubordinateRuntime.Get());
return m_JsContext->ExecuteScript(btScript.c_str(), hRetValue, pValue);
}
@@ -161,7 +165,8 @@
if (!ResolveObjects(refNode, propname, &resolveRs, dwFlag, nullptr))
return false;
if (resolveRs.dwFlags == XFA_ResolveNode_RSType_Nodes) {
- pValue->Assign(GetJSValueFromMap(resolveRs.objects.front().Get()));
+ pValue->Assign(
+ GetOrCreateJSBindingFromMap(resolveRs.objects.front().Get()));
return true;
}
if (resolveRs.dwFlags == XFA_ResolveNode_RSType_Attribute &&
@@ -228,7 +233,7 @@
CXFA_Object* pObj =
lpScriptContext->GetDocument()->GetXFAObject(uHashCode);
if (pObj) {
- pValue->Assign(lpScriptContext->GetJSValueFromMap(pObj));
+ pValue->Assign(lpScriptContext->GetOrCreateJSBindingFromMap(pObj));
return;
}
}
@@ -302,7 +307,7 @@
CXFA_Object* pObject =
lpScriptContext->GetVariablesThis(pOriginalObject, false);
if (wsPropName.EqualsASCII("xfa")) {
- CFXJSE_Value* pValue = lpScriptContext->GetJSValueFromMap(
+ CFXJSE_Value* pValue = lpScriptContext->GetOrCreateJSBindingFromMap(
lpScriptContext->GetDocument()->GetRoot());
pReturnValue->Assign(pValue);
return;
@@ -739,9 +744,7 @@
m_CacheList.push_back(std::move(pList));
}
-CFXJSE_Value* CFXJSE_Engine::GetJSValueFromMap(CXFA_Object* pObject) {
- if (!pObject)
- return nullptr;
+CFXJSE_Value* CFXJSE_Engine::GetOrCreateJSBindingFromMap(CXFA_Object* pObject) {
if (pObject->IsNode())
RunVariablesScript(pObject->AsNode());
@@ -750,13 +753,22 @@
return iter->second.get();
auto jsValue = pdfium::MakeUnique<CFXJSE_Value>(GetIsolate());
- jsValue->SetObject(pObject, m_pJsClass.Get());
+ jsValue->SetHostObject(pObject, m_pJsClass.Get());
CFXJSE_Value* pValue = jsValue.get();
m_mapObjectToValue.insert(std::make_pair(pObject, std::move(jsValue)));
return pValue;
}
+void CFXJSE_Engine::RemoveJSBindingFromMap(CXFA_Object* pObject) {
+ auto iter = m_mapObjectToValue.find(pObject);
+ if (iter == m_mapObjectToValue.end())
+ return;
+
+ iter->second->ClearHostObject();
+ m_mapObjectToValue.erase(iter);
+}
+
void CFXJSE_Engine::SetNodesOfRunScript(std::vector<CXFA_Node*>* pArray) {
m_pScriptNodeArray = pArray;
}
diff --git a/fxjs/xfa/cfxjse_engine.h b/fxjs/xfa/cfxjse_engine.h
index d96eaee..addf0cc 100644
--- a/fxjs/xfa/cfxjse_engine.h
+++ b/fxjs/xfa/cfxjse_engine.h
@@ -80,7 +80,10 @@
XFA_RESOLVENODE_RS* resolveNodeRS,
uint32_t dwStyles,
CXFA_Node* bindNode);
- CFXJSE_Value* GetJSValueFromMap(CXFA_Object* pObject);
+
+ CFXJSE_Value* GetOrCreateJSBindingFromMap(CXFA_Object* pObject);
+ void RemoveJSBindingFromMap(CXFA_Object* pObject);
+
void AddToCacheList(std::unique_ptr<CXFA_List> pList);
CXFA_Object* GetThisObject() const { return m_pThisObject.Get(); }
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 47b52a9..6782fb6 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -5438,8 +5438,8 @@
WideString::FromUTF8(bsAccessorName).AsStringView(), &resolveNodeRS,
dwFlags, nullptr);
if (bRet && resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
- accessorValue->Assign(
- pScriptContext->GetJSValueFromMap(resolveNodeRS.objects.front().Get()));
+ accessorValue->Assign(pScriptContext->GetOrCreateJSBindingFromMap(
+ resolveNodeRS.objects.front().Get()));
return true;
}
return false;
@@ -5517,7 +5517,7 @@
for (auto& pObject : resolveNodeRS.objects) {
resultValues->push_back(pdfium::MakeUnique<CFXJSE_Value>(pIsolate));
resultValues->back()->Assign(
- pScriptContext->GetJSValueFromMap(pObject.Get()));
+ pScriptContext->GetOrCreateJSBindingFromMap(pObject.Get()));
}
return;
}
@@ -5713,7 +5713,7 @@
: m_pIsolate(pScriptIsolate),
m_pValue(pdfium::MakeUnique<CFXJSE_Value>(pScriptIsolate)),
m_pDocument(pDoc) {
- m_pValue->SetObject(
+ m_pValue->SetHostObject(
this,
CFXJSE_Class::Create(pScriptContext, &kFormCalcFM2JSDescriptor, false));
}
diff --git a/fxjs/xfa/cfxjse_value.cpp b/fxjs/xfa/cfxjse_value.cpp
index 194e77d..eff4477 100644
--- a/fxjs/xfa/cfxjse_value.cpp
+++ b/fxjs/xfa/cfxjse_value.cpp
@@ -82,8 +82,8 @@
return FXJSE_RetrieveObjectBinding(pValue.As<v8::Object>());
}
-void CFXJSE_Value::SetObject(CFXJSE_HostObject* lpObject,
- CFXJSE_Class* pClass) {
+void CFXJSE_Value::SetHostObject(CFXJSE_HostObject* lpObject,
+ CFXJSE_Class* pClass) {
CFXJSE_ScopeUtil_IsolateHandleRootContext scope(GetIsolate());
v8::Local<v8::FunctionTemplate> hClass =
v8::Local<v8::FunctionTemplate>::New(GetIsolate(), pClass->m_hTemplate);
@@ -95,6 +95,13 @@
m_hValue.Reset(GetIsolate(), hObject);
}
+void CFXJSE_Value::ClearHostObject() {
+ CFXJSE_ScopeUtil_IsolateHandleRootContext scope(GetIsolate());
+ FXJSE_ClearObjectBinding(m_hValue.Get(GetIsolate()).As<v8::Object>());
+ v8::Local<v8::Value> hValue = v8::Null(GetIsolate());
+ m_hValue.Reset(GetIsolate(), hValue);
+}
+
void CFXJSE_Value::SetArray(
const std::vector<std::unique_ptr<CFXJSE_Value>>& values) {
CFXJSE_ScopeUtil_IsolateHandleRootContext scope(GetIsolate());
diff --git a/fxjs/xfa/cfxjse_value.h b/fxjs/xfa/cfxjse_value.h
index 5a81a80..aea43fd 100644
--- a/fxjs/xfa/cfxjse_value.h
+++ b/fxjs/xfa/cfxjse_value.h
@@ -52,7 +52,9 @@
void SetString(ByteStringView szString);
void SetFloat(float fFloat);
- void SetObject(CFXJSE_HostObject* lpObject, CFXJSE_Class* pClass);
+ void SetHostObject(CFXJSE_HostObject* lpObject, CFXJSE_Class* pClass);
+ void ClearHostObject();
+
void SetArray(const std::vector<std::unique_ptr<CFXJSE_Value>>& values);
void SetDate(double dDouble);
diff --git a/fxjs/xfa/cjx_exclgroup.cpp b/fxjs/xfa/cjx_exclgroup.cpp
index f24b7e6..ae20485 100644
--- a/fxjs/xfa/cjx_exclgroup.cpp
+++ b/fxjs/xfa/cjx_exclgroup.cpp
@@ -107,9 +107,8 @@
return CJS_Result::Success(runtime->NewNull());
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pReturnNode);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ pReturnNode);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
diff --git a/fxjs/xfa/cjx_form.cpp b/fxjs/xfa/cjx_form.cpp
index 41f7e45..32c884b 100644
--- a/fxjs/xfa/cjx_form.cpp
+++ b/fxjs/xfa/cjx_form.cpp
@@ -48,9 +48,9 @@
CXFA_ArrayNodeList* pFormNodes = new CXFA_ArrayNodeList(GetDocument());
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pFormNodes);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ pFormNodes);
+
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
}
diff --git a/fxjs/xfa/cjx_hostpseudomodel.cpp b/fxjs/xfa/cjx_hostpseudomodel.cpp
index 678b052..c5d36b3 100644
--- a/fxjs/xfa/cjx_hostpseudomodel.cpp
+++ b/fxjs/xfa/cjx_hostpseudomodel.cpp
@@ -474,9 +474,7 @@
return CJS_Result::Success();
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNode);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
diff --git a/fxjs/xfa/cjx_instancemanager.cpp b/fxjs/xfa/cjx_instancemanager.cpp
index 6d6de91..f3881e4 100644
--- a/fxjs/xfa/cjx_instancemanager.cpp
+++ b/fxjs/xfa/cjx_instancemanager.cpp
@@ -250,9 +250,8 @@
}
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ pNewInstance);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
@@ -296,9 +295,8 @@
}
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewInstance);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ pNewInstance);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
diff --git a/fxjs/xfa/cjx_model.cpp b/fxjs/xfa/cjx_model.cpp
index 66ae1ea..4fa0a2e 100644
--- a/fxjs/xfa/cjx_model.cpp
+++ b/fxjs/xfa/cjx_model.cpp
@@ -67,9 +67,7 @@
}
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pNewNode);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNewNode);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
diff --git a/fxjs/xfa/cjx_node.cpp b/fxjs/xfa/cjx_node.cpp
index 59c364a..bf10c0f 100644
--- a/fxjs/xfa/cjx_node.cpp
+++ b/fxjs/xfa/cjx_node.cpp
@@ -183,9 +183,8 @@
CXFA_Node* pCloneNode = GetXFANode()->Clone(runtime->ToBoolean(params[0]));
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pCloneNode);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ pCloneNode);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
@@ -219,9 +218,7 @@
return CJS_Result::Success(runtime->NewNull());
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNode);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
@@ -470,7 +467,7 @@
ThrowInvalidPropertyException();
return;
}
- pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(
+ pValue->Assign(GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
GetXFANode()->GetModelNode()));
}
@@ -509,8 +506,9 @@
std::vector<CXFA_Node*> properties = GetXFANode()->GetNodeList(
XFA_NODEFILTER_OneOfProperty, XFA_Element::Unknown);
if (!properties.empty()) {
- pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(
- properties.front()));
+ pValue->Assign(
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ properties.front()));
}
}
diff --git a/fxjs/xfa/cjx_object.cpp b/fxjs/xfa/cjx_object.cpp
index 7a5e082..63eb003 100644
--- a/fxjs/xfa/cjx_object.cpp
+++ b/fxjs/xfa/cjx_object.cpp
@@ -1507,8 +1507,8 @@
return;
}
- pValue->Assign(
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pDataNode));
+ pValue->Assign(GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ pDataNode));
}
void CJX_Object::ScriptSomMandatory(CFXJSE_Value* pValue,
diff --git a/fxjs/xfa/cjx_subform.cpp b/fxjs/xfa/cjx_subform.cpp
index 17739a1..18e1508 100644
--- a/fxjs/xfa/cjx_subform.cpp
+++ b/fxjs/xfa/cjx_subform.cpp
@@ -125,6 +125,6 @@
return;
}
- pValue->Assign(
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pInstanceMgr));
+ pValue->Assign(GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(
+ pInstanceMgr));
}
diff --git a/fxjs/xfa/cjx_tree.cpp b/fxjs/xfa/cjx_tree.cpp
index c036ab9..cc13b7a 100644
--- a/fxjs/xfa/cjx_tree.cpp
+++ b/fxjs/xfa/cjx_tree.cpp
@@ -58,9 +58,7 @@
if (resolveNodeRS.dwFlags == XFA_ResolveNode_RSType_Nodes) {
CXFA_Object* pObject = resolveNodeRS.objects.front().Get();
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pObject);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pObject);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
@@ -139,7 +137,7 @@
CFXJSE_Engine* pScriptContext = GetDocument()->GetScriptContext();
CXFA_AttachNodeList* pNodeList =
new CXFA_AttachNodeList(GetDocument(), ToNode(GetXFAObject()));
- pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
+ pValue->SetHostObject(pNodeList, pScriptContext->GetJseNormalClass());
}
void CJX_Tree::parent(CFXJSE_Value* pValue,
@@ -156,7 +154,8 @@
return;
}
- pValue->Assign(GetDocument()->GetScriptContext()->GetJSValueFromMap(pParent));
+ pValue->Assign(
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pParent));
}
void CJX_Tree::index(CFXJSE_Value* pValue,
@@ -230,5 +229,5 @@
}
}
}
- pValue->SetObject(pNodeList, pScriptContext->GetJseNormalClass());
+ pValue->SetHostObject(pNodeList, pScriptContext->GetJseNormalClass());
}
diff --git a/fxjs/xfa/cjx_treelist.cpp b/fxjs/xfa/cjx_treelist.cpp
index 04a27e7..51bbb0a 100644
--- a/fxjs/xfa/cjx_treelist.cpp
+++ b/fxjs/xfa/cjx_treelist.cpp
@@ -44,9 +44,7 @@
return CJS_Result::Success();
CFXJSE_Value* value =
- GetDocument()->GetScriptContext()->GetJSValueFromMap(pNode);
- if (!value)
- return CJS_Result::Success(runtime->NewNull());
+ GetDocument()->GetScriptContext()->GetOrCreateJSBindingFromMap(pNode);
return CJS_Result::Success(
value->DirectGetValue().Get(runtime->GetIsolate()));
diff --git a/fxjs/xfa/cjx_xfa.cpp b/fxjs/xfa/cjx_xfa.cpp
index 2d943bd..08c6a80 100644
--- a/fxjs/xfa/cjx_xfa.cpp
+++ b/fxjs/xfa/cjx_xfa.cpp
@@ -31,5 +31,5 @@
pValue->SetNull();
return;
}
- pValue->Assign(pScriptContext->GetJSValueFromMap(pThis));
+ pValue->Assign(pScriptContext->GetOrCreateJSBindingFromMap(pThis));
}
diff --git a/xfa/fxfa/parser/cxfa_document.cpp b/xfa/fxfa/parser/cxfa_document.cpp
index 9200ec2..a30cb54 100644
--- a/xfa/fxfa/parser/cxfa_document.cpp
+++ b/xfa/fxfa/parser/cxfa_document.cpp
@@ -1437,8 +1437,6 @@
return m_pScriptContext.get();
}
-// We have to call |InitScriptContext| before any calls to |GetScriptContext|
-// or the context won't have an isolate set into it.
CFXJSE_Engine* CXFA_Document::GetScriptContext() const {
ASSERT(m_pScriptContext);
return m_pScriptContext.get();
diff --git a/xfa/fxfa/parser/cxfa_document.h b/xfa/fxfa/parser/cxfa_document.h
index 4a57a177..f8fec25 100644
--- a/xfa/fxfa/parser/cxfa_document.h
+++ b/xfa/fxfa/parser/cxfa_document.h
@@ -59,7 +59,13 @@
explicit CXFA_Document(CXFA_FFNotify* notify);
~CXFA_Document() override;
+ bool HasScriptContext() const { return !!m_pScriptContext; }
CFXJSE_Engine* InitScriptContext(CJS_Runtime* fxjs_runtime);
+
+ // Only safe to call in situations where the context is known to exist,
+ // and always returns non-NULL in those situations. In other words, we have
+ // to call InitScriptContext() first to avoid a situation where the context
+ // won't have an isolate set into it.
CFXJSE_Engine* GetScriptContext() const;
CXFA_FFNotify* GetNotify() const { return notify_.Get(); }
diff --git a/xfa/fxfa/parser/cxfa_nodeowner.cpp b/xfa/fxfa/parser/cxfa_nodeowner.cpp
index 13c969c..6ee9fd8 100644
--- a/xfa/fxfa/parser/cxfa_nodeowner.cpp
+++ b/xfa/fxfa/parser/cxfa_nodeowner.cpp
@@ -13,7 +13,9 @@
CXFA_NodeOwner::CXFA_NodeOwner() = default;
-CXFA_NodeOwner::~CXFA_NodeOwner() = default;
+CXFA_NodeOwner::~CXFA_NodeOwner() {
+ is_being_destroyed_ = true;
+}
CXFA_Node* CXFA_NodeOwner::AddOwnedNode(std::unique_ptr<CXFA_Node> node) {
if (!node)
diff --git a/xfa/fxfa/parser/cxfa_nodeowner.h b/xfa/fxfa/parser/cxfa_nodeowner.h
index 2aaabe4..e7247cd 100644
--- a/xfa/fxfa/parser/cxfa_nodeowner.h
+++ b/xfa/fxfa/parser/cxfa_nodeowner.h
@@ -18,10 +18,12 @@
CXFA_Node* AddOwnedNode(std::unique_ptr<CXFA_Node> node);
void FreeOwnedNode(CXFA_Node* node);
+ bool IsBeingDestroyed() const { return is_being_destroyed_; }
protected:
CXFA_NodeOwner();
+ bool is_being_destroyed_ = false;
std::set<std::unique_ptr<CXFA_Node>> nodes_;
};
diff --git a/xfa/fxfa/parser/cxfa_object.cpp b/xfa/fxfa/parser/cxfa_object.cpp
index a541991..6d730bf 100644
--- a/xfa/fxfa/parser/cxfa_object.cpp
+++ b/xfa/fxfa/parser/cxfa_object.cpp
@@ -30,7 +30,10 @@
m_elementNameHash(FX_HashCode_GetAsIfW(m_elementName, false)),
m_pJSObject(std::move(jsObject)) {}
-CXFA_Object::~CXFA_Object() = default;
+CXFA_Object::~CXFA_Object() {
+ if (!GetDocument()->IsBeingDestroyed() && GetDocument()->HasScriptContext())
+ GetDocument()->GetScriptContext()->RemoveJSBindingFromMap(this);
+}
CXFA_Object* CXFA_Object::AsCXFAObject() {
return this;