1 // Copyright 2014 The PDFium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #ifndef FXJS_XFA_CFXJSE_ENGINE_H_ 8 #define FXJS_XFA_CFXJSE_ENGINE_H_ 9 10 #include <map> 11 #include <memory> 12 #include <type_traits> 13 #include <vector> 14 15 #include "core/fxcrt/mask.h" 16 #include "core/fxcrt/unowned_ptr.h" 17 #include "fxjs/cfx_v8.h" 18 #include "v8/include/cppgc/persistent.h" 19 #include "v8/include/v8-forward.h" 20 #include "v8/include/v8-persistent-handle.h" 21 #include "xfa/fxfa/cxfa_eventparam.h" 22 #include "xfa/fxfa/parser/cxfa_document.h" 23 #include "xfa/fxfa/parser/cxfa_script.h" 24 #include "xfa/fxfa/parser/xfa_basic_data.h" 25 26 class CFXJSE_Class; 27 class CFXJSE_Context; 28 class CFXJSE_FormCalcContext; 29 class CFXJSE_HostObject; 30 class CFXJSE_NodeHelper; 31 class CFXJSE_ResolveProcessor; 32 class CFXJSE_Value; 33 class CJS_Runtime; 34 35 enum class XFA_ResolveFlag : uint16_t { 36 kChildren = 1 << 0, 37 kTagName = 1 << 1, 38 kAttributes = 1 << 2, 39 kProperties = 1 << 3, 40 kSiblings = 1 << 5, 41 kParent = 1 << 6, 42 kAnyChild = 1 << 7, 43 kALL = 1 << 8, 44 kCreateNode = 1 << 10, 45 kBind = 1 << 11, 46 kBindNew = 1 << 12, 47 }; 48 49 class CFXJSE_Engine final : public CFX_V8 { 50 public: 51 class ResolveResult { 52 CPPGC_STACK_ALLOCATED(); // Allow raw/unowned pointers. 53 54 public: 55 enum class Type { 56 kNodes = 0, 57 kAttribute, 58 kCreateNodeOne, 59 kCreateNodeAll, 60 kCreateNodeMidAll, 61 kExistNodes, 62 }; 63 64 ResolveResult(); 65 ResolveResult(const ResolveResult& that); 66 ResolveResult& operator=(const ResolveResult& that); 67 ~ResolveResult(); 68 69 Type type = Type::kNodes; 70 XFA_SCRIPTATTRIBUTEINFO script_attribute = {}; 71 72 // Vector of Member would be correct for stack-based vectors, if 73 // STL worked with cppgc. 74 std::vector<cppgc::Member<CXFA_Object>> objects; 75 }; 76 77 static CXFA_Object* ToObject(const v8::FunctionCallbackInfo<v8::Value>& info); 78 static CXFA_Object* ToObject(v8::Isolate* pIsolate, 79 v8::Local<v8::Value> value); 80 static CXFA_Object* ToObject(v8::Isolate* pIsolate, CFXJSE_Value* pValue); 81 static CXFA_Object* ToObject(CFXJSE_HostObject* pHostObj); 82 static v8::Local<v8::Value> GlobalPropertyGetter( 83 v8::Isolate* pIsolate, 84 v8::Local<v8::Object> pObject, 85 ByteStringView szPropName); 86 static void GlobalPropertySetter(v8::Isolate* pIsolate, 87 v8::Local<v8::Object> pObject, 88 ByteStringView szPropName, 89 v8::Local<v8::Value> pValue); 90 static v8::Local<v8::Value> NormalPropertyGetter( 91 v8::Isolate* pIsolate, 92 v8::Local<v8::Object> pObject, 93 ByteStringView szPropName); 94 static void NormalPropertySetter(v8::Isolate* pIsolate, 95 v8::Local<v8::Object> pObject, 96 ByteStringView szPropName, 97 v8::Local<v8::Value> pValue); 98 static CJS_Result NormalMethodCall( 99 const v8::FunctionCallbackInfo<v8::Value>& info, 100 const WideString& functionName); 101 static FXJSE_ClassPropType NormalPropTypeGetter(v8::Isolate* pIsolate, 102 v8::Local<v8::Object> pObject, 103 ByteStringView szPropName, 104 bool bQueryIn); 105 static FXJSE_ClassPropType GlobalPropTypeGetter(v8::Isolate* pIsolate, 106 v8::Local<v8::Object> pObject, 107 ByteStringView szPropName, 108 bool bQueryIn); 109 110 CFXJSE_Engine(CXFA_Document* pDocument, CJS_Runtime* fxjs_runtime); 111 ~CFXJSE_Engine() override; 112 113 class EventParamScope { 114 CPPGC_STACK_ALLOCATED(); 115 116 public: 117 EventParamScope(CFXJSE_Engine* pEngine, 118 CXFA_Node* pTarget, 119 CXFA_EventParam* pEventParam); 120 ~EventParamScope(); 121 122 private: 123 UnownedPtr<CFXJSE_Engine> m_pEngine; 124 UnownedPtr<CXFA_Node> m_pPrevTarget; 125 UnownedPtr<CXFA_EventParam> m_pPrevEventParam; 126 }; 127 friend class EventParamScope; 128 GetEventTarget()129 CXFA_Node* GetEventTarget() const { return m_pTarget; } GetEventParam()130 CXFA_EventParam* GetEventParam() const { return m_eventParam; } 131 bool RunScript(CXFA_Script::Type eScriptType, 132 WideStringView wsScript, 133 CFXJSE_Value* pRetValue, 134 CXFA_Object* pThisObject); 135 136 absl::optional<ResolveResult> ResolveObjects(CXFA_Object* refObject, 137 WideStringView wsExpression, 138 Mask<XFA_ResolveFlag> dwStyles); 139 140 absl::optional<ResolveResult> ResolveObjectsWithBindNode( 141 CXFA_Object* refObject, 142 WideStringView wsExpression, 143 Mask<XFA_ResolveFlag> dwStyles, 144 CXFA_Node* bindNode); 145 146 v8::Local<v8::Object> GetOrCreateJSBindingFromMap(CXFA_Object* pObject); 147 GetThisObject()148 CXFA_Object* GetThisObject() const { return m_pThisObject; } GetJseNormalClass()149 CFXJSE_Class* GetJseNormalClass() const { return m_pJsClass; } GetDocument()150 CXFA_Document* GetDocument() const { return m_pDocument.Get(); } 151 152 void SetNodesOfRunScript(std::vector<cppgc::Persistent<CXFA_Node>>* pArray); 153 void AddNodesOfRunScript(CXFA_Node* pNode); 154 SetRunAtType(XFA_AttributeValue eRunAt)155 void SetRunAtType(XFA_AttributeValue eRunAt) { m_eRunAtType = eRunAt; } IsRunAtClient()156 bool IsRunAtClient() { return m_eRunAtType != XFA_AttributeValue::Server; } 157 158 CXFA_Script::Type GetType(); 159 160 void AddObjectToUpArray(CXFA_Node* pNode); 161 CXFA_Node* LastObjectFromUpArray(); 162 163 CXFA_Object* ToXFAObject(v8::Local<v8::Value> obj); 164 v8::Local<v8::Object> NewNormalXFAObject(CXFA_Object* obj); 165 IsResolvingNodes()166 bool IsResolvingNodes() const { return m_bResolvingNodes; } 167 GetJseContextForTest()168 CFXJSE_Context* GetJseContextForTest() const { return GetJseContext(); } 169 170 private: GetJseContext()171 CFXJSE_Context* GetJseContext() const { return m_JsContext.get(); } 172 CFXJSE_Context* CreateVariablesContext(CXFA_Script* pScriptNode, 173 CXFA_Node* pSubform); 174 void RemoveBuiltInObjs(CFXJSE_Context* pContext); 175 bool QueryNodeByFlag(CXFA_Node* refNode, 176 WideStringView propname, 177 v8::Local<v8::Value>* pValue, 178 Mask<XFA_ResolveFlag> dwFlag); 179 bool UpdateNodeByFlag(CXFA_Node* refNode, 180 WideStringView propname, 181 v8::Local<v8::Value> pValue, 182 Mask<XFA_ResolveFlag> dwFlag); 183 bool IsStrictScopeInJavaScript(); 184 CXFA_Object* GetVariablesThis(CXFA_Object* pObject); 185 CXFA_Object* GetVariablesScript(CXFA_Object* pObject); 186 CFXJSE_Context* VariablesContextForScriptNode(CXFA_Script* pScriptNode); 187 bool QueryVariableValue(CXFA_Script* pScriptNode, 188 ByteStringView szPropName, 189 v8::Local<v8::Value>* pValue); 190 bool UpdateVariableValue(CXFA_Script* pScriptNode, 191 ByteStringView szPropName, 192 v8::Local<v8::Value> pValue); 193 void RunVariablesScript(CXFA_Script* pScriptNode); 194 195 UnownedPtr<CJS_Runtime> const m_pSubordinateRuntime; 196 cppgc::WeakPersistent<CXFA_Document> const m_pDocument; 197 std::unique_ptr<CFXJSE_Context> m_JsContext; 198 UnownedPtr<CFXJSE_Class> m_pJsClass; 199 CXFA_Script::Type m_eScriptType = CXFA_Script::Type::Unknown; 200 // |m_mapObjectToValue| is what ensures the v8 object bound to a 201 // CJX_Object remains valid for the lifetime of the engine. 202 std::map<cppgc::Persistent<CJX_Object>, v8::Global<v8::Object>> 203 m_mapObjectToObject; 204 std::map<cppgc::Persistent<CJX_Object>, std::unique_ptr<CFXJSE_Context>> 205 m_mapVariableToContext; 206 cppgc::Persistent<CXFA_Node> m_pTarget; 207 UnownedPtr<CXFA_EventParam> m_eventParam; 208 std::vector<cppgc::Persistent<CXFA_Node>> m_upObjectArray; 209 UnownedPtr<std::vector<cppgc::Persistent<CXFA_Node>>> m_pScriptNodeArray; 210 std::unique_ptr<CFXJSE_NodeHelper> const m_NodeHelper; 211 std::unique_ptr<CFXJSE_ResolveProcessor> const m_ResolveProcessor; 212 std::unique_ptr<CFXJSE_FormCalcContext> m_FormCalcContext; 213 cppgc::Persistent<CXFA_Object> m_pThisObject; 214 XFA_AttributeValue m_eRunAtType = XFA_AttributeValue::Client; 215 bool m_bResolvingNodes = false; 216 }; 217 218 #endif // FXJS_XFA_CFXJSE_ENGINE_H_ 219