Make ownership of CXFA_ThisProxy explicit (and sane).
Keep a reference to it in the CXFJSE_Context for later clean-up
rather than trying to retrieve it though bound V8 objects.
-- Make constructor private while we're at it.
Change-Id: Id80b7cb53b33ec30ed349b4fa0d01afe5f5456b9
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/71653
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 953448d..0606037 100644
--- a/fxjs/xfa/cfxjse_context.cpp
+++ b/fxjs/xfa/cfxjse_context.cpp
@@ -15,6 +15,7 @@
#include "fxjs/xfa/cfxjse_runtimedata.h"
#include "fxjs/xfa/cfxjse_value.h"
#include "fxjs/xfa/cjx_object.h"
+#include "third_party/base/ptr_util.h"
#include "xfa/fxfa/parser/cxfa_thisproxy.h"
namespace {
@@ -130,15 +131,6 @@
hObject->SetAlignedPointerInInternalField(1, nullptr);
}
-CXFA_ThisProxy* ToThisProxy(CFXJSE_Value* pValue) {
- CFXJSE_HostObject* pHostObject = pValue->ToHostObject();
- if (!pHostObject)
- return nullptr;
-
- CJX_Object* pJSObject = pHostObject->AsCJXObject();
- return pJSObject ? ToThisProxy(pJSObject->GetXFAObject()) : nullptr;
-}
-
} // namespace
void FXJSE_UpdateObjectBinding(v8::Local<v8::Object> hObject,
@@ -184,9 +176,13 @@
std::unique_ptr<CFXJSE_Context> CFXJSE_Context::Create(
v8::Isolate* pIsolate,
const FXJSE_CLASS_DESCRIPTOR* pGlobalClass,
- CFXJSE_HostObject* pGlobalObject) {
+ CFXJSE_HostObject* pGlobalObject,
+ std::unique_ptr<CXFA_ThisProxy> pProxy) {
CFXJSE_ScopeUtil_IsolateHandle scope(pIsolate);
- auto pContext = std::make_unique<CFXJSE_Context>(pIsolate);
+
+ // Private constructor.
+ auto pContext =
+ pdfium::WrapUnique(new CFXJSE_Context(pIsolate, std::move(pProxy)));
v8::Local<v8::ObjectTemplate> hObjectTemplate;
if (pGlobalClass) {
CFXJSE_Class* pGlobalClassObj =
@@ -218,14 +214,11 @@
return pContext;
}
-CFXJSE_Context::CFXJSE_Context(v8::Isolate* pIsolate) : m_pIsolate(pIsolate) {}
+CFXJSE_Context::CFXJSE_Context(v8::Isolate* pIsolate,
+ std::unique_ptr<CXFA_ThisProxy> pProxy)
+ : m_pIsolate(pIsolate), m_pProxy(std::move(pProxy)) {}
-CFXJSE_Context::~CFXJSE_Context() {
- // This is what prevents leaking the CXFA_ThisProxies allocated in
- // CXFJSE_Engine::CreateVariablesContext(). If the global object is
- // not a thisproxy, then this degenerates to deleting nullptr, a no-op.
- delete ToThisProxy(GetGlobalObject().get());
-}
+CFXJSE_Context::~CFXJSE_Context() = default;
std::unique_ptr<CFXJSE_Value> CFXJSE_Context::GetGlobalObject() {
auto pValue = std::make_unique<CFXJSE_Value>(GetIsolate());
diff --git a/fxjs/xfa/cfxjse_context.h b/fxjs/xfa/cfxjse_context.h
index 417cf23..ed302f0 100644
--- a/fxjs/xfa/cfxjse_context.h
+++ b/fxjs/xfa/cfxjse_context.h
@@ -17,6 +17,7 @@
class CFXJSE_Class;
class CFXJSE_HostObject;
class CFXJSE_Value;
+class CXFA_ThisProxy;
struct FXJSE_CLASS_DESCRIPTOR;
class CFXJSE_Context {
@@ -24,9 +25,9 @@
static std::unique_ptr<CFXJSE_Context> Create(
v8::Isolate* pIsolate,
const FXJSE_CLASS_DESCRIPTOR* pGlobalClass,
- CFXJSE_HostObject* pGlobalObject);
+ CFXJSE_HostObject* pGlobalObject,
+ std::unique_ptr<CXFA_ThisProxy> pProxy);
- explicit CFXJSE_Context(v8::Isolate* pIsolate);
~CFXJSE_Context();
v8::Isolate* GetIsolate() const { return m_pIsolate.Get(); }
@@ -40,12 +41,14 @@
CFXJSE_Value* lpNewThisObject);
private:
+ CFXJSE_Context(v8::Isolate* pIsolate, std::unique_ptr<CXFA_ThisProxy> pProxy);
CFXJSE_Context(const CFXJSE_Context&) = delete;
CFXJSE_Context& operator=(const CFXJSE_Context&) = delete;
v8::Global<v8::Context> m_hContext;
UnownedPtr<v8::Isolate> m_pIsolate;
std::vector<std::unique_ptr<CFXJSE_Class>> m_rgClasses;
+ std::unique_ptr<CXFA_ThisProxy> m_pProxy;
};
void FXJSE_UpdateObjectBinding(v8::Local<v8::Object> hObject,
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp
index fbfd008..44836c9 100644
--- a/fxjs/xfa/cfxjse_engine.cpp
+++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -108,7 +108,8 @@
m_pDocument(pDocument),
m_JsContext(CFXJSE_Context::Create(fxjs_runtime->GetIsolate(),
&GlobalClassDescriptor,
- pDocument->GetRoot()->JSObject())),
+ pDocument->GetRoot()->JSObject(),
+ nullptr)),
m_ResolveProcessor(std::make_unique<CFXJSE_ResolveProcessor>()) {
RemoveBuiltInObjs(m_JsContext.get());
m_JsContext->EnableCompatibleMode();
@@ -499,12 +500,10 @@
if (!pScriptNode || !pSubform)
return nullptr;
- // Ownership of |proxy| is maintained through v8 bindings, and is
- // manually freed in ~CFXJE_Context() after re-obtaining the binding
- // from v8.
- auto* proxy = new CXFA_ThisProxy(pSubform, pScriptNode);
+ auto proxy = std::make_unique<CXFA_ThisProxy>(pSubform, pScriptNode);
+ CJX_Object* js_object = proxy->JSObject();
auto pNewContext = CFXJSE_Context::Create(
- GetIsolate(), &VariablesClassDescriptor, proxy->JSObject());
+ GetIsolate(), &VariablesClassDescriptor, js_object, std::move(proxy));
RemoveBuiltInObjs(pNewContext.get());
pNewContext->EnableCompatibleMode();
CFXJSE_Context* pResult = pNewContext.get();
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index d93f3b7..f25c263 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -28,6 +28,7 @@
#include "xfa/fxfa/parser/cxfa_document.h"
#include "xfa/fxfa/parser/cxfa_localevalue.h"
#include "xfa/fxfa/parser/cxfa_node.h"
+#include "xfa/fxfa/parser/cxfa_thisproxy.h"
#include "xfa/fxfa/parser/cxfa_timezoneprovider.h"
#include "xfa/fxfa/parser/xfa_utils.h"
@@ -3208,7 +3209,7 @@
}
std::unique_ptr<CFXJSE_Context> pNewContext(
- CFXJSE_Context::Create(pIsolate, nullptr, nullptr));
+ CFXJSE_Context::Create(pIsolate, nullptr, nullptr, nullptr));
auto returnValue = std::make_unique<CFXJSE_Value>(pIsolate);
pNewContext->ExecuteScript(