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 "fxjs/xfa/cfxjse_context.h" 19 #include "v8/include/cppgc/persistent.h" 20 #include "v8/include/v8-forward.h" 21 #include "v8/include/v8-persistent-handle.h" 22 #include "xfa/fxfa/cxfa_eventparam.h" 23 #include "xfa/fxfa/parser/cxfa_document.h" 24 #include "xfa/fxfa/parser/cxfa_script.h" 25 #include "xfa/fxfa/parser/xfa_basic_data.h" 26 27 class CFXJSE_Class; 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(ResolveResult&& that) noexcept; 66 ResolveResult& operator=(ResolveResult&& that) noexcept; 67 68 // Move-only type. 69 ResolveResult(const ResolveResult& that) = delete; 70 ResolveResult& operator=(const ResolveResult& that) = delete; 71 72 ~ResolveResult(); 73 74 Type type = Type::kNodes; 75 XFA_SCRIPTATTRIBUTEINFO script_attribute = {}; 76 77 // Vector of Member would be correct for stack-based vectors, if 78 // STL worked with cppgc. 79 std::vector<cppgc::Member<CXFA_Object>> objects; 80 }; 81 82 static CXFA_Object* ToObject(const v8::FunctionCallbackInfo<v8::Value>& info); 83 static CXFA_Object* ToObject(v8::Isolate* pIsolate, 84 v8::Local<v8::Value> value); 85 static CXFA_Object* ToObject(v8::Isolate* pIsolate, CFXJSE_Value* pValue); 86 static CXFA_Object* ToObject(CFXJSE_HostObject* pHostObj); 87 static v8::Local<v8::Value> GlobalPropertyGetter( 88 v8::Isolate* pIsolate, 89 v8::Local<v8::Object> pObject, 90 ByteStringView szPropName); 91 static void GlobalPropertySetter(v8::Isolate* pIsolate, 92 v8::Local<v8::Object> pObject, 93 ByteStringView szPropName, 94 v8::Local<v8::Value> pValue); 95 static v8::Local<v8::Value> NormalPropertyGetter( 96 v8::Isolate* pIsolate, 97 v8::Local<v8::Object> pObject, 98 ByteStringView szPropName); 99 static void NormalPropertySetter(v8::Isolate* pIsolate, 100 v8::Local<v8::Object> pObject, 101 ByteStringView szPropName, 102 v8::Local<v8::Value> pValue); 103 static CJS_Result NormalMethodCall( 104 const v8::FunctionCallbackInfo<v8::Value>& info, 105 const WideString& functionName); 106 static FXJSE_ClassPropType NormalPropTypeGetter(v8::Isolate* pIsolate, 107 v8::Local<v8::Object> pObject, 108 ByteStringView szPropName, 109 bool bQueryIn); 110 static FXJSE_ClassPropType GlobalPropTypeGetter(v8::Isolate* pIsolate, 111 v8::Local<v8::Object> pObject, 112 ByteStringView szPropName, 113 bool bQueryIn); 114 115 CFXJSE_Engine(CXFA_Document* pDocument, CJS_Runtime* fxjs_runtime); 116 ~CFXJSE_Engine() override; 117 118 class EventParamScope { 119 CPPGC_STACK_ALLOCATED(); 120 121 public: 122 EventParamScope(CFXJSE_Engine* pEngine, 123 CXFA_Node* pTarget, 124 CXFA_EventParam* pEventParam); 125 ~EventParamScope(); 126 127 private: 128 UnownedPtr<CFXJSE_Engine> m_pEngine; 129 UnownedPtr<CXFA_Node> m_pPrevTarget; 130 UnownedPtr<CXFA_EventParam> m_pPrevEventParam; 131 }; 132 friend class EventParamScope; 133 GetEventTarget()134 CXFA_Node* GetEventTarget() const { return m_pTarget; } GetEventParam()135 CXFA_EventParam* GetEventParam() const { return m_eventParam; } 136 137 CFXJSE_Context::ExecutionResult RunScript(CXFA_Script::Type eScriptType, 138 WideStringView wsScript, 139 CXFA_Object* pThisObject); 140 141 std::optional<ResolveResult> ResolveObjects(CXFA_Object* refObject, 142 WideStringView wsExpression, 143 Mask<XFA_ResolveFlag> dwStyles); 144 145 std::optional<ResolveResult> ResolveObjectsWithBindNode( 146 CXFA_Object* refObject, 147 WideStringView wsExpression, 148 Mask<XFA_ResolveFlag> dwStyles, 149 CXFA_Node* bindNode); 150 151 v8::Local<v8::Object> GetOrCreateJSBindingFromMap(CXFA_Object* pObject); 152 GetThisObject()153 CXFA_Object* GetThisObject() const { return m_pThisObject; } GetJseNormalClass()154 CFXJSE_Class* GetJseNormalClass() const { return m_pJsClass; } GetDocument()155 CXFA_Document* GetDocument() const { return m_pDocument.Get(); } 156 157 void SetNodesOfRunScript(std::vector<cppgc::Persistent<CXFA_Node>>* pArray); 158 void AddNodesOfRunScript(CXFA_Node* pNode); 159 SetRunAtType(XFA_AttributeValue eRunAt)160 void SetRunAtType(XFA_AttributeValue eRunAt) { m_eRunAtType = eRunAt; } IsRunAtClient()161 bool IsRunAtClient() { return m_eRunAtType != XFA_AttributeValue::Server; } 162 163 CXFA_Script::Type GetType(); 164 165 void AddObjectToUpArray(CXFA_Node* pNode); 166 CXFA_Node* LastObjectFromUpArray(); 167 168 CXFA_Object* ToXFAObject(v8::Local<v8::Value> obj); 169 v8::Local<v8::Object> NewNormalXFAObject(CXFA_Object* obj); 170 IsResolvingNodes()171 bool IsResolvingNodes() const { return m_bResolvingNodes; } 172 GetJseContextForTest()173 CFXJSE_Context* GetJseContextForTest() const { return GetJseContext(); } 174 175 private: GetJseContext()176 CFXJSE_Context* GetJseContext() const { return m_JsContext.get(); } 177 CFXJSE_Context* CreateVariablesContext(CXFA_Script* pScriptNode, 178 CXFA_Node* pSubform); 179 void RemoveBuiltInObjs(CFXJSE_Context* pContext); 180 bool QueryNodeByFlag(CXFA_Node* refNode, 181 WideStringView propname, 182 v8::Local<v8::Value>* pValue, 183 Mask<XFA_ResolveFlag> dwFlag); 184 bool UpdateNodeByFlag(CXFA_Node* refNode, 185 WideStringView propname, 186 v8::Local<v8::Value> pValue, 187 Mask<XFA_ResolveFlag> dwFlag); 188 bool IsStrictScopeInJavaScript(); 189 CXFA_Object* GetVariablesThis(CXFA_Object* pObject); 190 CXFA_Object* GetVariablesScript(CXFA_Object* pObject); 191 CFXJSE_Context* VariablesContextForScriptNode(CXFA_Script* pScriptNode); 192 bool QueryVariableValue(CXFA_Script* pScriptNode, 193 ByteStringView szPropName, 194 v8::Local<v8::Value>* pValue); 195 bool UpdateVariableValue(CXFA_Script* pScriptNode, 196 ByteStringView szPropName, 197 v8::Local<v8::Value> pValue); 198 void RunVariablesScript(CXFA_Script* pScriptNode); 199 200 UnownedPtr<CJS_Runtime> const m_pSubordinateRuntime; 201 cppgc::WeakPersistent<CXFA_Document> const m_pDocument; 202 std::unique_ptr<CFXJSE_Context> m_JsContext; 203 UnownedPtr<CFXJSE_Class> m_pJsClass; 204 CXFA_Script::Type m_eScriptType = CXFA_Script::Type::Unknown; 205 // |m_mapObjectToValue| is what ensures the v8 object bound to a 206 // CJX_Object remains valid for the lifetime of the engine. 207 std::map<cppgc::Persistent<CJX_Object>, v8::Global<v8::Object>> 208 m_mapObjectToObject; 209 std::map<cppgc::Persistent<CJX_Object>, std::unique_ptr<CFXJSE_Context>> 210 m_mapVariableToContext; 211 cppgc::Persistent<CXFA_Node> m_pTarget; 212 UnownedPtr<CXFA_EventParam> m_eventParam; 213 std::vector<cppgc::Persistent<CXFA_Node>> m_upObjectArray; 214 UnownedPtr<std::vector<cppgc::Persistent<CXFA_Node>>> m_pScriptNodeArray; 215 std::unique_ptr<CFXJSE_NodeHelper> const m_NodeHelper; 216 std::unique_ptr<CFXJSE_ResolveProcessor> const m_ResolveProcessor; 217 std::unique_ptr<CFXJSE_FormCalcContext> m_FormCalcContext; 218 cppgc::Persistent<CXFA_Object> m_pThisObject; 219 XFA_AttributeValue m_eRunAtType = XFA_AttributeValue::Client; 220 bool m_bResolvingNodes = false; 221 }; 222 223 #endif // FXJS_XFA_CFXJSE_ENGINE_H_ 224