| // 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. | 
 |  | 
 | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 
 |  | 
 | #ifndef FXJS_XFA_CFXJSE_ENGINE_H_ | 
 | #define FXJS_XFA_CFXJSE_ENGINE_H_ | 
 |  | 
 | #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/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_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; | 
 |  | 
 | 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(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, | 
 |                                    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, | 
 |                                    v8::Local<v8::Value> pValue); | 
 |   static CJS_Result NormalMethodCall( | 
 |       const v8::FunctionCallbackInfo<v8::Value>& info, | 
 |       const WideString& functionName); | 
 |   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; | 
 |  | 
 |   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); | 
 |  | 
 |   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); | 
 |  | 
 |   v8::Local<v8::Object> GetOrCreateJSBindingFromMap(CXFA_Object* pObject); | 
 |  | 
 |   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<cppgc::Persistent<CXFA_Node>>* pArray); | 
 |   void AddNodesOfRunScript(CXFA_Node* pNode); | 
 |  | 
 |   void SetRunAtType(XFA_AttributeValue eRunAt) { m_eRunAtType = eRunAt; } | 
 |   bool IsRunAtClient() { return m_eRunAtType != XFA_AttributeValue::Server; } | 
 |  | 
 |   CXFA_Script::Type GetType(); | 
 |  | 
 |   void AddObjectToUpArray(CXFA_Node* pNode); | 
 |   CXFA_Node* LastObjectFromUpArray(); | 
 |  | 
 |   CXFA_Object* ToXFAObject(v8::Local<v8::Value> obj); | 
 |   v8::Local<v8::Object> NewNormalXFAObject(CXFA_Object* obj); | 
 |  | 
 |   bool IsResolvingNodes() const { return m_bResolvingNodes; } | 
 |  | 
 |   CFXJSE_Context* GetJseContextForTest() const { return GetJseContext(); } | 
 |  | 
 |  private: | 
 |   CFXJSE_Context* GetJseContext() const { return m_JsContext.get(); } | 
 |   CFXJSE_Context* CreateVariablesContext(CXFA_Script* pScriptNode, | 
 |                                          CXFA_Node* pSubform); | 
 |   void RemoveBuiltInObjs(CFXJSE_Context* pContext); | 
 |   bool QueryNodeByFlag(CXFA_Node* refNode, | 
 |                        WideStringView propname, | 
 |                        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); | 
 |   CXFA_Object* GetVariablesScript(CXFA_Object* pObject); | 
 |   CFXJSE_Context* VariablesContextForScriptNode(CXFA_Script* pScriptNode); | 
 |   bool QueryVariableValue(CXFA_Script* pScriptNode, | 
 |                           ByteStringView szPropName, | 
 |                           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; | 
 |   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; | 
 |   // |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<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_FormCalcContext; | 
 |   cppgc::Persistent<CXFA_Object> m_pThisObject; | 
 |   XFA_AttributeValue m_eRunAtType = XFA_AttributeValue::Client; | 
 |   bool m_bResolvingNodes = false; | 
 | }; | 
 |  | 
 | #endif  //  FXJS_XFA_CFXJSE_ENGINE_H_ |