• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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