• 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 "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