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