diff options
Diffstat (limited to 'fxjs/xfa/cfxjse_engine.h')
-rw-r--r-- | fxjs/xfa/cfxjse_engine.h | 217 |
1 files changed, 147 insertions, 70 deletions
diff --git a/fxjs/xfa/cfxjse_engine.h b/fxjs/xfa/cfxjse_engine.h index addf0cc58..c6a95c311 100644 --- a/fxjs/xfa/cfxjse_engine.h +++ b/fxjs/xfa/cfxjse_engine.h @@ -1,4 +1,4 @@ -// Copyright 2014 PDFium Authors. All rights reserved. +// Copyright 2014 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,133 +9,210 @@ #include <map> #include <memory> +#include <type_traits> #include <vector> +#include "core/fxcrt/mask.h" #include "core/fxcrt/unowned_ptr.h" #include "fxjs/cfx_v8.h" -#include "v8/include/v8.h" +#include "v8/include/cppgc/persistent.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-persistent-handle.h" #include "xfa/fxfa/cxfa_eventparam.h" #include "xfa/fxfa/parser/cxfa_document.h" #include "xfa/fxfa/parser/cxfa_script.h" -#include "xfa/fxfa/parser/xfa_resolvenode_rs.h" +#include "xfa/fxfa/parser/xfa_basic_data.h" class CFXJSE_Class; class CFXJSE_Context; class CFXJSE_FormCalcContext; +class CFXJSE_HostObject; +class CFXJSE_NodeHelper; class CFXJSE_ResolveProcessor; +class CFXJSE_Value; class CJS_Runtime; -class CXFA_List; - -// Flags for |dwStyles| argument to CFXJSE_Engine::ResolveObjects(). -#define XFA_RESOLVENODE_Children 0x0001 -#define XFA_RESOLVENODE_TagName 0x0002 -#define XFA_RESOLVENODE_Attributes 0x0004 -#define XFA_RESOLVENODE_Properties 0x0008 -#define XFA_RESOLVENODE_Siblings 0x0020 -#define XFA_RESOLVENODE_Parent 0x0040 -#define XFA_RESOLVENODE_AnyChild 0x0080 -#define XFA_RESOLVENODE_ALL 0x0100 -#define XFA_RESOLVENODE_CreateNode 0x0400 -#define XFA_RESOLVENODE_Bind 0x0800 -#define XFA_RESOLVENODE_BindNew 0x1000 + +enum class XFA_ResolveFlag : uint16_t { + kChildren = 1 << 0, + kTagName = 1 << 1, + kAttributes = 1 << 2, + kProperties = 1 << 3, + kSiblings = 1 << 5, + kParent = 1 << 6, + kAnyChild = 1 << 7, + kALL = 1 << 8, + kCreateNode = 1 << 10, + kBind = 1 << 11, + kBindNew = 1 << 12, +}; class CFXJSE_Engine final : public CFX_V8 { public: + class ResolveResult { + CPPGC_STACK_ALLOCATED(); // Allow raw/unowned pointers. + + public: + enum class Type { + kNodes = 0, + kAttribute, + kCreateNodeOne, + kCreateNodeAll, + kCreateNodeMidAll, + kExistNodes, + }; + + ResolveResult(); + ResolveResult(const ResolveResult& that); + ResolveResult& operator=(const ResolveResult& that); + ~ResolveResult(); + + Type type = Type::kNodes; + XFA_SCRIPTATTRIBUTEINFO script_attribute = {}; + + // Vector of Member would be correct for stack-based vectors, if + // STL worked with cppgc. + std::vector<cppgc::Member<CXFA_Object>> objects; + }; + static CXFA_Object* ToObject(const v8::FunctionCallbackInfo<v8::Value>& info); - static CXFA_Object* ToObject(CFXJSE_Value* pValue); - static void GlobalPropertyGetter(CFXJSE_Value* pObject, - ByteStringView szPropName, - CFXJSE_Value* pValue); - static void GlobalPropertySetter(CFXJSE_Value* pObject, + static CXFA_Object* ToObject(v8::Isolate* pIsolate, + v8::Local<v8::Value> value); + static CXFA_Object* ToObject(v8::Isolate* pIsolate, CFXJSE_Value* pValue); + static CXFA_Object* ToObject(CFXJSE_HostObject* pHostObj); + static v8::Local<v8::Value> GlobalPropertyGetter( + v8::Isolate* pIsolate, + v8::Local<v8::Object> pObject, + ByteStringView szPropName); + static void GlobalPropertySetter(v8::Isolate* pIsolate, + v8::Local<v8::Object> pObject, ByteStringView szPropName, - CFXJSE_Value* pValue); - static void NormalPropertyGetter(CFXJSE_Value* pObject, + v8::Local<v8::Value> pValue); + static v8::Local<v8::Value> NormalPropertyGetter( + v8::Isolate* pIsolate, + v8::Local<v8::Object> pObject, + ByteStringView szPropName); + static void NormalPropertySetter(v8::Isolate* pIsolate, + v8::Local<v8::Object> pObject, ByteStringView szPropName, - CFXJSE_Value* pValue); - static void NormalPropertySetter(CFXJSE_Value* pObject, - ByteStringView szPropName, - CFXJSE_Value* pValue); + v8::Local<v8::Value> pValue); static CJS_Result NormalMethodCall( const v8::FunctionCallbackInfo<v8::Value>& info, const WideString& functionName); - static int32_t NormalPropTypeGetter(CFXJSE_Value* pObject, - ByteStringView szPropName, - bool bQueryIn); - static int32_t GlobalPropTypeGetter(CFXJSE_Value* pObject, - ByteStringView szPropName, - bool bQueryIn); + static FXJSE_ClassPropType NormalPropTypeGetter(v8::Isolate* pIsolate, + v8::Local<v8::Object> pObject, + ByteStringView szPropName, + bool bQueryIn); + static FXJSE_ClassPropType GlobalPropTypeGetter(v8::Isolate* pIsolate, + v8::Local<v8::Object> pObject, + ByteStringView szPropName, + bool bQueryIn); CFXJSE_Engine(CXFA_Document* pDocument, CJS_Runtime* fxjs_runtime); ~CFXJSE_Engine() override; - void SetEventParam(CXFA_EventParam* param) { m_eventParam = param; } - CXFA_EventParam* GetEventParam() const { return m_eventParam.Get(); } + class EventParamScope { + CPPGC_STACK_ALLOCATED(); + + public: + EventParamScope(CFXJSE_Engine* pEngine, + CXFA_Node* pTarget, + CXFA_EventParam* pEventParam); + ~EventParamScope(); + + private: + UnownedPtr<CFXJSE_Engine> m_pEngine; + UnownedPtr<CXFA_Node> m_pPrevTarget; + UnownedPtr<CXFA_EventParam> m_pPrevEventParam; + }; + friend class EventParamScope; + + CXFA_Node* GetEventTarget() const { return m_pTarget; } + CXFA_EventParam* GetEventParam() const { return m_eventParam; } bool RunScript(CXFA_Script::Type eScriptType, WideStringView wsScript, CFXJSE_Value* pRetValue, CXFA_Object* pThisObject); - bool ResolveObjects(CXFA_Object* refObject, - WideStringView wsExpression, - XFA_RESOLVENODE_RS* resolveNodeRS, - uint32_t dwStyles, - CXFA_Node* bindNode); + absl::optional<ResolveResult> ResolveObjects(CXFA_Object* refObject, + WideStringView wsExpression, + Mask<XFA_ResolveFlag> dwStyles); + + absl::optional<ResolveResult> ResolveObjectsWithBindNode( + CXFA_Object* refObject, + WideStringView wsExpression, + Mask<XFA_ResolveFlag> dwStyles, + CXFA_Node* bindNode); - CFXJSE_Value* GetOrCreateJSBindingFromMap(CXFA_Object* pObject); - void RemoveJSBindingFromMap(CXFA_Object* pObject); + v8::Local<v8::Object> GetOrCreateJSBindingFromMap(CXFA_Object* pObject); - void AddToCacheList(std::unique_ptr<CXFA_List> pList); - CXFA_Object* GetThisObject() const { return m_pThisObject.Get(); } + CXFA_Object* GetThisObject() const { return m_pThisObject; } + CFXJSE_Class* GetJseNormalClass() const { return m_pJsClass; } + CXFA_Document* GetDocument() const { return m_pDocument.Get(); } - void SetNodesOfRunScript(std::vector<CXFA_Node*>* pArray); + void SetNodesOfRunScript(std::vector<cppgc::Persistent<CXFA_Node>>* pArray); void AddNodesOfRunScript(CXFA_Node* pNode); - CFXJSE_Class* GetJseNormalClass() const { return m_pJsClass.Get(); } void SetRunAtType(XFA_AttributeValue eRunAt) { m_eRunAtType = eRunAt; } bool IsRunAtClient() { return m_eRunAtType != XFA_AttributeValue::Server; } CXFA_Script::Type GetType(); - std::vector<CXFA_Node*>* GetUpObjectArray() { return &m_upObjectArray; } - CXFA_Document* GetDocument() const { return m_pDocument.Get(); } + + void AddObjectToUpArray(CXFA_Node* pNode); + CXFA_Node* LastObjectFromUpArray(); CXFA_Object* ToXFAObject(v8::Local<v8::Value> obj); - v8::Local<v8::Value> NewXFAObject(CXFA_Object* obj, - v8::Global<v8::FunctionTemplate>& tmpl); + v8::Local<v8::Object> NewNormalXFAObject(CXFA_Object* obj); + + bool IsResolvingNodes() const { return m_bResolvingNodes; } + + CFXJSE_Context* GetJseContextForTest() const { return GetJseContext(); } private: - CFXJSE_Context* CreateVariablesContext(CXFA_Node* pScriptNode, + CFXJSE_Context* GetJseContext() const { return m_JsContext.get(); } + CFXJSE_Context* CreateVariablesContext(CXFA_Script* pScriptNode, CXFA_Node* pSubform); - void RemoveBuiltInObjs(CFXJSE_Context* pContext) const; + void RemoveBuiltInObjs(CFXJSE_Context* pContext); bool QueryNodeByFlag(CXFA_Node* refNode, WideStringView propname, - CFXJSE_Value* pValue, - uint32_t dwFlag, - bool bSetting); + v8::Local<v8::Value>* pValue, + Mask<XFA_ResolveFlag> dwFlag); + bool UpdateNodeByFlag(CXFA_Node* refNode, + WideStringView propname, + v8::Local<v8::Value> pValue, + Mask<XFA_ResolveFlag> dwFlag); bool IsStrictScopeInJavaScript(); - CXFA_Object* GetVariablesThis(CXFA_Object* pObject, bool bScriptNode); - bool QueryVariableValue(CXFA_Node* pScriptNode, + CXFA_Object* GetVariablesThis(CXFA_Object* pObject); + CXFA_Object* GetVariablesScript(CXFA_Object* pObject); + CFXJSE_Context* VariablesContextForScriptNode(CXFA_Script* pScriptNode); + bool QueryVariableValue(CXFA_Script* pScriptNode, ByteStringView szPropName, - CFXJSE_Value* pValue, - bool bGetter); - bool RunVariablesScript(CXFA_Node* pScriptNode); + v8::Local<v8::Value>* pValue); + bool UpdateVariableValue(CXFA_Script* pScriptNode, + ByteStringView szPropName, + v8::Local<v8::Value> pValue); + void RunVariablesScript(CXFA_Script* pScriptNode); UnownedPtr<CJS_Runtime> const m_pSubordinateRuntime; - UnownedPtr<CXFA_Document> const m_pDocument; + cppgc::WeakPersistent<CXFA_Document> const m_pDocument; std::unique_ptr<CFXJSE_Context> m_JsContext; UnownedPtr<CFXJSE_Class> m_pJsClass; CXFA_Script::Type m_eScriptType = CXFA_Script::Type::Unknown; - std::map<CXFA_Object*, std::unique_ptr<CFXJSE_Value>> m_mapObjectToValue; - std::map<CXFA_Object*, std::unique_ptr<CFXJSE_Context>> + // |m_mapObjectToValue| is what ensures the v8 object bound to a + // CJX_Object remains valid for the lifetime of the engine. + std::map<cppgc::Persistent<CJX_Object>, v8::Global<v8::Object>> + m_mapObjectToObject; + std::map<cppgc::Persistent<CJX_Object>, std::unique_ptr<CFXJSE_Context>> m_mapVariableToContext; + cppgc::Persistent<CXFA_Node> m_pTarget; UnownedPtr<CXFA_EventParam> m_eventParam; - std::vector<CXFA_Node*> m_upObjectArray; - // CacheList holds the List items so we can clean them up when we're done. - std::vector<std::unique_ptr<CXFA_List>> m_CacheList; - UnownedPtr<std::vector<CXFA_Node*>> m_pScriptNodeArray; + std::vector<cppgc::Persistent<CXFA_Node>> m_upObjectArray; + UnownedPtr<std::vector<cppgc::Persistent<CXFA_Node>>> m_pScriptNodeArray; + std::unique_ptr<CFXJSE_NodeHelper> const m_NodeHelper; std::unique_ptr<CFXJSE_ResolveProcessor> const m_ResolveProcessor; - std::unique_ptr<CFXJSE_FormCalcContext> m_FM2JSContext; - UnownedPtr<CXFA_Object> m_pThisObject; + std::unique_ptr<CFXJSE_FormCalcContext> m_FormCalcContext; + cppgc::Persistent<CXFA_Object> m_pThisObject; XFA_AttributeValue m_eRunAtType = XFA_AttributeValue::Client; + bool m_bResolvingNodes = false; }; #endif // FXJS_XFA_CFXJSE_ENGINE_H_ |