xref: /aosp_15_r20/external/pdfium/fxjs/xfa/cfxjse_engine.cpp (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 #include "fxjs/xfa/cfxjse_engine.h"
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
10*3ac0a46fSAndroid Build Coastguard Worker 
11*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/autorestorer.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_extension.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/stl_util.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/widetext_buffer.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/cjs_runtime.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/fxv8.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_class.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_context.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_formcalc_context.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_isolatetracker.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_nodehelper.h"
22*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_resolveprocessor.h"
23*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cfxjse_value.h"
24*3ac0a46fSAndroid Build Coastguard Worker #include "fxjs/xfa/cjx_object.h"
25*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/containers/contains.h"
26*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-function-callback.h"
27*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-function.h"
28*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-object.h"
29*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_eventparam.h"
30*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffdoc.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/cxfa_ffnotify.h"
32*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_document.h"
33*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_localemgr.h"
34*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_node.h"
35*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_object.h"
36*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_thisproxy.h"
37*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/cxfa_variables.h"
38*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_basic_data.h"
39*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fxfa/parser/xfa_utils.h"
40*3ac0a46fSAndroid Build Coastguard Worker 
41*3ac0a46fSAndroid Build Coastguard Worker using pdfium::fxjse::kClassTag;
42*3ac0a46fSAndroid Build Coastguard Worker 
43*3ac0a46fSAndroid Build Coastguard Worker const FXJSE_CLASS_DESCRIPTOR kGlobalClassDescriptor = {
44*3ac0a46fSAndroid Build Coastguard Worker     kClassTag,  // tag
45*3ac0a46fSAndroid Build Coastguard Worker     "Root",     // name
46*3ac0a46fSAndroid Build Coastguard Worker     nullptr,    // methods
47*3ac0a46fSAndroid Build Coastguard Worker     0,          // method count
48*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::GlobalPropTypeGetter,
49*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::GlobalPropertyGetter,
50*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::GlobalPropertySetter,
51*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::NormalMethodCall,
52*3ac0a46fSAndroid Build Coastguard Worker };
53*3ac0a46fSAndroid Build Coastguard Worker 
54*3ac0a46fSAndroid Build Coastguard Worker const FXJSE_CLASS_DESCRIPTOR kNormalClassDescriptor = {
55*3ac0a46fSAndroid Build Coastguard Worker     kClassTag,    // tag
56*3ac0a46fSAndroid Build Coastguard Worker     "XFAObject",  // name
57*3ac0a46fSAndroid Build Coastguard Worker     nullptr,      // methods
58*3ac0a46fSAndroid Build Coastguard Worker     0,            // method count
59*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::NormalPropTypeGetter,
60*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::NormalPropertyGetter,
61*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::NormalPropertySetter,
62*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::NormalMethodCall,
63*3ac0a46fSAndroid Build Coastguard Worker };
64*3ac0a46fSAndroid Build Coastguard Worker 
65*3ac0a46fSAndroid Build Coastguard Worker const FXJSE_CLASS_DESCRIPTOR kVariablesClassDescriptor = {
66*3ac0a46fSAndroid Build Coastguard Worker     kClassTag,          // tag
67*3ac0a46fSAndroid Build Coastguard Worker     "XFAScriptObject",  // name
68*3ac0a46fSAndroid Build Coastguard Worker     nullptr,            // methods
69*3ac0a46fSAndroid Build Coastguard Worker     0,                  // method count
70*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::NormalPropTypeGetter,
71*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::GlobalPropertyGetter,
72*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::GlobalPropertySetter,
73*3ac0a46fSAndroid Build Coastguard Worker     CFXJSE_Engine::NormalMethodCall,
74*3ac0a46fSAndroid Build Coastguard Worker };
75*3ac0a46fSAndroid Build Coastguard Worker 
76*3ac0a46fSAndroid Build Coastguard Worker namespace {
77*3ac0a46fSAndroid Build Coastguard Worker 
78*3ac0a46fSAndroid Build Coastguard Worker const char kFormCalcRuntime[] = "pfm_rt";
79*3ac0a46fSAndroid Build Coastguard Worker 
80*3ac0a46fSAndroid Build Coastguard Worker }  // namespace
81*3ac0a46fSAndroid Build Coastguard Worker 
82*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult::ResolveResult() = default;
83*3ac0a46fSAndroid Build Coastguard Worker 
84*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult::ResolveResult(const ResolveResult& that) =
85*3ac0a46fSAndroid Build Coastguard Worker     default;
86*3ac0a46fSAndroid Build Coastguard Worker 
87*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult& CFXJSE_Engine::ResolveResult::operator=(
88*3ac0a46fSAndroid Build Coastguard Worker     const ResolveResult& that) = default;
89*3ac0a46fSAndroid Build Coastguard Worker 
90*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveResult::~ResolveResult() = default;
91*3ac0a46fSAndroid Build Coastguard Worker 
92*3ac0a46fSAndroid Build Coastguard Worker // static
ToObject(const v8::FunctionCallbackInfo<v8::Value> & info)93*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CFXJSE_Engine::ToObject(
94*3ac0a46fSAndroid Build Coastguard Worker     const v8::FunctionCallbackInfo<v8::Value>& info) {
95*3ac0a46fSAndroid Build Coastguard Worker   return ToObject(info.GetIsolate(), info.Holder());
96*3ac0a46fSAndroid Build Coastguard Worker }
97*3ac0a46fSAndroid Build Coastguard Worker 
98*3ac0a46fSAndroid Build Coastguard Worker // static
ToObject(v8::Isolate * pIsolate,v8::Local<v8::Value> value)99*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CFXJSE_Engine::ToObject(v8::Isolate* pIsolate,
100*3ac0a46fSAndroid Build Coastguard Worker                                      v8::Local<v8::Value> value) {
101*3ac0a46fSAndroid Build Coastguard Worker   if (!value->IsObject())
102*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
103*3ac0a46fSAndroid Build Coastguard Worker 
104*3ac0a46fSAndroid Build Coastguard Worker   return ToObject(FXJSE_RetrieveObjectBinding(value.As<v8::Object>()));
105*3ac0a46fSAndroid Build Coastguard Worker }
106*3ac0a46fSAndroid Build Coastguard Worker 
107*3ac0a46fSAndroid Build Coastguard Worker // static.
ToObject(v8::Isolate * pIsolate,CFXJSE_Value * pValue)108*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CFXJSE_Engine::ToObject(v8::Isolate* pIsolate,
109*3ac0a46fSAndroid Build Coastguard Worker                                      CFXJSE_Value* pValue) {
110*3ac0a46fSAndroid Build Coastguard Worker   return ToObject(pValue->ToHostObject(pIsolate));
111*3ac0a46fSAndroid Build Coastguard Worker }
112*3ac0a46fSAndroid Build Coastguard Worker 
113*3ac0a46fSAndroid Build Coastguard Worker // static
ToObject(CFXJSE_HostObject * pHostObj)114*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CFXJSE_Engine::ToObject(CFXJSE_HostObject* pHostObj) {
115*3ac0a46fSAndroid Build Coastguard Worker   if (!pHostObj)
116*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
117*3ac0a46fSAndroid Build Coastguard Worker 
118*3ac0a46fSAndroid Build Coastguard Worker   CJX_Object* pJSObject = pHostObj->AsCJXObject();
119*3ac0a46fSAndroid Build Coastguard Worker   return pJSObject ? pJSObject->GetXFAObject() : nullptr;
120*3ac0a46fSAndroid Build Coastguard Worker }
121*3ac0a46fSAndroid Build Coastguard Worker 
CFXJSE_Engine(CXFA_Document * pDocument,CJS_Runtime * fxjs_runtime)122*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::CFXJSE_Engine(CXFA_Document* pDocument,
123*3ac0a46fSAndroid Build Coastguard Worker                              CJS_Runtime* fxjs_runtime)
124*3ac0a46fSAndroid Build Coastguard Worker     : CFX_V8(fxjs_runtime->GetIsolate()),
125*3ac0a46fSAndroid Build Coastguard Worker       m_pSubordinateRuntime(fxjs_runtime),
126*3ac0a46fSAndroid Build Coastguard Worker       m_pDocument(pDocument),
127*3ac0a46fSAndroid Build Coastguard Worker       m_JsContext(CFXJSE_Context::Create(fxjs_runtime->GetIsolate(),
128*3ac0a46fSAndroid Build Coastguard Worker                                          &kGlobalClassDescriptor,
129*3ac0a46fSAndroid Build Coastguard Worker                                          pDocument->GetRoot()->JSObject(),
130*3ac0a46fSAndroid Build Coastguard Worker                                          nullptr)),
131*3ac0a46fSAndroid Build Coastguard Worker       m_NodeHelper(std::make_unique<CFXJSE_NodeHelper>()),
132*3ac0a46fSAndroid Build Coastguard Worker       m_ResolveProcessor(
133*3ac0a46fSAndroid Build Coastguard Worker           std::make_unique<CFXJSE_ResolveProcessor>(this, m_NodeHelper.get())) {
134*3ac0a46fSAndroid Build Coastguard Worker   RemoveBuiltInObjs(m_JsContext.get());
135*3ac0a46fSAndroid Build Coastguard Worker   m_JsContext->EnableCompatibleMode();
136*3ac0a46fSAndroid Build Coastguard Worker 
137*3ac0a46fSAndroid Build Coastguard Worker   // Don't know if this can happen before we remove the builtin objs and set
138*3ac0a46fSAndroid Build Coastguard Worker   // compatibility mode.
139*3ac0a46fSAndroid Build Coastguard Worker   m_pJsClass =
140*3ac0a46fSAndroid Build Coastguard Worker       CFXJSE_Class::Create(m_JsContext.get(), &kNormalClassDescriptor, false);
141*3ac0a46fSAndroid Build Coastguard Worker }
142*3ac0a46fSAndroid Build Coastguard Worker 
~CFXJSE_Engine()143*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::~CFXJSE_Engine() {
144*3ac0a46fSAndroid Build Coastguard Worker   // This is what ensures that the v8 object bound to a CJX_Object
145*3ac0a46fSAndroid Build Coastguard Worker   // no longer retains that binding since it will outlive that object.
146*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
147*3ac0a46fSAndroid Build Coastguard Worker   for (const auto& pair : m_mapObjectToObject) {
148*3ac0a46fSAndroid Build Coastguard Worker     const v8::Global<v8::Object>& binding = pair.second;
149*3ac0a46fSAndroid Build Coastguard Worker     FXJSE_ClearObjectBinding(v8::Local<v8::Object>::New(GetIsolate(), binding));
150*3ac0a46fSAndroid Build Coastguard Worker   }
151*3ac0a46fSAndroid Build Coastguard Worker }
152*3ac0a46fSAndroid Build Coastguard Worker 
EventParamScope(CFXJSE_Engine * pEngine,CXFA_Node * pTarget,CXFA_EventParam * pEventParam)153*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::EventParamScope::EventParamScope(CFXJSE_Engine* pEngine,
154*3ac0a46fSAndroid Build Coastguard Worker                                                 CXFA_Node* pTarget,
155*3ac0a46fSAndroid Build Coastguard Worker                                                 CXFA_EventParam* pEventParam)
156*3ac0a46fSAndroid Build Coastguard Worker     : m_pEngine(pEngine),
157*3ac0a46fSAndroid Build Coastguard Worker       m_pPrevTarget(pEngine->GetEventTarget()),
158*3ac0a46fSAndroid Build Coastguard Worker       m_pPrevEventParam(pEngine->GetEventParam()) {
159*3ac0a46fSAndroid Build Coastguard Worker   m_pEngine->m_pTarget = pTarget;
160*3ac0a46fSAndroid Build Coastguard Worker   m_pEngine->m_eventParam = pEventParam;
161*3ac0a46fSAndroid Build Coastguard Worker }
162*3ac0a46fSAndroid Build Coastguard Worker 
~EventParamScope()163*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::EventParamScope::~EventParamScope() {
164*3ac0a46fSAndroid Build Coastguard Worker   m_pEngine->m_pTarget = m_pPrevTarget;
165*3ac0a46fSAndroid Build Coastguard Worker   m_pEngine->m_eventParam = m_pPrevEventParam;
166*3ac0a46fSAndroid Build Coastguard Worker }
167*3ac0a46fSAndroid Build Coastguard Worker 
RunScript(CXFA_Script::Type eScriptType,WideStringView wsScript,CFXJSE_Value * hRetValue,CXFA_Object * pThisObject)168*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_Engine::RunScript(CXFA_Script::Type eScriptType,
169*3ac0a46fSAndroid Build Coastguard Worker                               WideStringView wsScript,
170*3ac0a46fSAndroid Build Coastguard Worker                               CFXJSE_Value* hRetValue,
171*3ac0a46fSAndroid Build Coastguard Worker                               CXFA_Object* pThisObject) {
172*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
173*3ac0a46fSAndroid Build Coastguard Worker   AutoRestorer<CXFA_Script::Type> typeRestorer(&m_eScriptType);
174*3ac0a46fSAndroid Build Coastguard Worker   m_eScriptType = eScriptType;
175*3ac0a46fSAndroid Build Coastguard Worker 
176*3ac0a46fSAndroid Build Coastguard Worker   ByteString btScript;
177*3ac0a46fSAndroid Build Coastguard Worker   if (eScriptType == CXFA_Script::Type::Formcalc) {
178*3ac0a46fSAndroid Build Coastguard Worker     if (!m_FormCalcContext) {
179*3ac0a46fSAndroid Build Coastguard Worker       m_FormCalcContext = std::make_unique<CFXJSE_FormCalcContext>(
180*3ac0a46fSAndroid Build Coastguard Worker           GetIsolate(), m_JsContext.get(), m_pDocument.Get());
181*3ac0a46fSAndroid Build Coastguard Worker     }
182*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<WideTextBuffer> wsJavaScript =
183*3ac0a46fSAndroid Build Coastguard Worker         CFXJSE_FormCalcContext::Translate(m_pDocument->GetHeap(), wsScript);
184*3ac0a46fSAndroid Build Coastguard Worker     if (!wsJavaScript.has_value()) {
185*3ac0a46fSAndroid Build Coastguard Worker       hRetValue->SetUndefined(GetIsolate());
186*3ac0a46fSAndroid Build Coastguard Worker       return false;
187*3ac0a46fSAndroid Build Coastguard Worker     }
188*3ac0a46fSAndroid Build Coastguard Worker     btScript = FX_UTF8Encode(wsJavaScript.value().AsStringView());
189*3ac0a46fSAndroid Build Coastguard Worker   } else {
190*3ac0a46fSAndroid Build Coastguard Worker     btScript = FX_UTF8Encode(wsScript);
191*3ac0a46fSAndroid Build Coastguard Worker   }
192*3ac0a46fSAndroid Build Coastguard Worker   AutoRestorer<cppgc::Persistent<CXFA_Object>> nodeRestorer(&m_pThisObject);
193*3ac0a46fSAndroid Build Coastguard Worker   m_pThisObject = pThisObject;
194*3ac0a46fSAndroid Build Coastguard Worker 
195*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Object> pThisBinding;
196*3ac0a46fSAndroid Build Coastguard Worker   if (pThisObject)
197*3ac0a46fSAndroid Build Coastguard Worker     pThisBinding = GetOrCreateJSBindingFromMap(pThisObject);
198*3ac0a46fSAndroid Build Coastguard Worker 
199*3ac0a46fSAndroid Build Coastguard Worker   IJS_Runtime::ScopedEventContext ctx(m_pSubordinateRuntime);
200*3ac0a46fSAndroid Build Coastguard Worker   return m_JsContext->ExecuteScript(btScript.AsStringView(), hRetValue,
201*3ac0a46fSAndroid Build Coastguard Worker                                     pThisBinding);
202*3ac0a46fSAndroid Build Coastguard Worker }
203*3ac0a46fSAndroid Build Coastguard Worker 
QueryNodeByFlag(CXFA_Node * refNode,WideStringView propname,v8::Local<v8::Value> * pValue,Mask<XFA_ResolveFlag> dwFlag)204*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_Engine::QueryNodeByFlag(CXFA_Node* refNode,
205*3ac0a46fSAndroid Build Coastguard Worker                                     WideStringView propname,
206*3ac0a46fSAndroid Build Coastguard Worker                                     v8::Local<v8::Value>* pValue,
207*3ac0a46fSAndroid Build Coastguard Worker                                     Mask<XFA_ResolveFlag> dwFlag) {
208*3ac0a46fSAndroid Build Coastguard Worker   if (!refNode)
209*3ac0a46fSAndroid Build Coastguard Worker     return false;
210*3ac0a46fSAndroid Build Coastguard Worker 
211*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
212*3ac0a46fSAndroid Build Coastguard Worker       ResolveObjects(refNode, propname, dwFlag);
213*3ac0a46fSAndroid Build Coastguard Worker   if (!maybeResult.has_value())
214*3ac0a46fSAndroid Build Coastguard Worker     return false;
215*3ac0a46fSAndroid Build Coastguard Worker 
216*3ac0a46fSAndroid Build Coastguard Worker   if (maybeResult.value().type == ResolveResult::Type::kNodes) {
217*3ac0a46fSAndroid Build Coastguard Worker     *pValue =
218*3ac0a46fSAndroid Build Coastguard Worker         GetOrCreateJSBindingFromMap(maybeResult.value().objects.front().Get());
219*3ac0a46fSAndroid Build Coastguard Worker     return true;
220*3ac0a46fSAndroid Build Coastguard Worker   }
221*3ac0a46fSAndroid Build Coastguard Worker   if (maybeResult.value().type == ResolveResult::Type::kAttribute &&
222*3ac0a46fSAndroid Build Coastguard Worker       maybeResult.value().script_attribute.callback) {
223*3ac0a46fSAndroid Build Coastguard Worker     CJX_Object* jsObject = maybeResult.value().objects.front()->JSObject();
224*3ac0a46fSAndroid Build Coastguard Worker     (*maybeResult.value().script_attribute.callback)(
225*3ac0a46fSAndroid Build Coastguard Worker         GetIsolate(), jsObject, pValue, false,
226*3ac0a46fSAndroid Build Coastguard Worker         maybeResult.value().script_attribute.attribute);
227*3ac0a46fSAndroid Build Coastguard Worker   }
228*3ac0a46fSAndroid Build Coastguard Worker   return true;
229*3ac0a46fSAndroid Build Coastguard Worker }
230*3ac0a46fSAndroid Build Coastguard Worker 
UpdateNodeByFlag(CXFA_Node * refNode,WideStringView propname,v8::Local<v8::Value> pValue,Mask<XFA_ResolveFlag> dwFlag)231*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_Engine::UpdateNodeByFlag(CXFA_Node* refNode,
232*3ac0a46fSAndroid Build Coastguard Worker                                      WideStringView propname,
233*3ac0a46fSAndroid Build Coastguard Worker                                      v8::Local<v8::Value> pValue,
234*3ac0a46fSAndroid Build Coastguard Worker                                      Mask<XFA_ResolveFlag> dwFlag) {
235*3ac0a46fSAndroid Build Coastguard Worker   if (!refNode)
236*3ac0a46fSAndroid Build Coastguard Worker     return false;
237*3ac0a46fSAndroid Build Coastguard Worker 
238*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
239*3ac0a46fSAndroid Build Coastguard Worker       ResolveObjects(refNode, propname, dwFlag);
240*3ac0a46fSAndroid Build Coastguard Worker   if (!maybeResult.has_value())
241*3ac0a46fSAndroid Build Coastguard Worker     return false;
242*3ac0a46fSAndroid Build Coastguard Worker 
243*3ac0a46fSAndroid Build Coastguard Worker   if (maybeResult.value().type == ResolveResult::Type::kAttribute &&
244*3ac0a46fSAndroid Build Coastguard Worker       maybeResult.value().script_attribute.callback) {
245*3ac0a46fSAndroid Build Coastguard Worker     CJX_Object* jsObject = maybeResult.value().objects.front()->JSObject();
246*3ac0a46fSAndroid Build Coastguard Worker     (*maybeResult.value().script_attribute.callback)(
247*3ac0a46fSAndroid Build Coastguard Worker         GetIsolate(), jsObject, &pValue, true,
248*3ac0a46fSAndroid Build Coastguard Worker         maybeResult.value().script_attribute.attribute);
249*3ac0a46fSAndroid Build Coastguard Worker   }
250*3ac0a46fSAndroid Build Coastguard Worker   return true;
251*3ac0a46fSAndroid Build Coastguard Worker }
252*3ac0a46fSAndroid Build Coastguard Worker 
253*3ac0a46fSAndroid Build Coastguard Worker // static
GlobalPropertySetter(v8::Isolate * pIsolate,v8::Local<v8::Object> pObject,ByteStringView szPropName,v8::Local<v8::Value> pValue)254*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_Engine::GlobalPropertySetter(v8::Isolate* pIsolate,
255*3ac0a46fSAndroid Build Coastguard Worker                                          v8::Local<v8::Object> pObject,
256*3ac0a46fSAndroid Build Coastguard Worker                                          ByteStringView szPropName,
257*3ac0a46fSAndroid Build Coastguard Worker                                          v8::Local<v8::Value> pValue) {
258*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pOriginalNode = ToObject(pIsolate, pObject);
259*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Document* pDoc = pOriginalNode->GetDocument();
260*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Engine* pScriptContext = pDoc->GetScriptContext();
261*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pRefNode = ToNode(pScriptContext->GetThisObject());
262*3ac0a46fSAndroid Build Coastguard Worker   if (pOriginalNode->IsThisProxy())
263*3ac0a46fSAndroid Build Coastguard Worker     pRefNode = ToNode(pScriptContext->GetVariablesThis(pOriginalNode));
264*3ac0a46fSAndroid Build Coastguard Worker 
265*3ac0a46fSAndroid Build Coastguard Worker   WideString wsPropName = WideString::FromUTF8(szPropName);
266*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptContext->UpdateNodeByFlag(
267*3ac0a46fSAndroid Build Coastguard Worker           pRefNode, wsPropName.AsStringView(), pValue,
268*3ac0a46fSAndroid Build Coastguard Worker           Mask<XFA_ResolveFlag>{
269*3ac0a46fSAndroid Build Coastguard Worker               XFA_ResolveFlag::kParent, XFA_ResolveFlag::kSiblings,
270*3ac0a46fSAndroid Build Coastguard Worker               XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kProperties,
271*3ac0a46fSAndroid Build Coastguard Worker               XFA_ResolveFlag::kAttributes})) {
272*3ac0a46fSAndroid Build Coastguard Worker     return;
273*3ac0a46fSAndroid Build Coastguard Worker   }
274*3ac0a46fSAndroid Build Coastguard Worker   if (pOriginalNode->IsThisProxy() && fxv8::IsUndefined(pValue)) {
275*3ac0a46fSAndroid Build Coastguard Worker     fxv8::ReentrantDeleteObjectPropertyHelper(pScriptContext->GetIsolate(),
276*3ac0a46fSAndroid Build Coastguard Worker                                               pObject, szPropName);
277*3ac0a46fSAndroid Build Coastguard Worker     return;
278*3ac0a46fSAndroid Build Coastguard Worker   }
279*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = pDoc->GetNotify();
280*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
281*3ac0a46fSAndroid Build Coastguard Worker     return;
282*3ac0a46fSAndroid Build Coastguard Worker 
283*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
284*3ac0a46fSAndroid Build Coastguard Worker   auto* pCJSRuntime = static_cast<CJS_Runtime*>(hDoc->GetIJSRuntime());
285*3ac0a46fSAndroid Build Coastguard Worker   if (!pCJSRuntime)
286*3ac0a46fSAndroid Build Coastguard Worker     return;
287*3ac0a46fSAndroid Build Coastguard Worker 
288*3ac0a46fSAndroid Build Coastguard Worker   IJS_Runtime::ScopedEventContext pContext(pCJSRuntime);
289*3ac0a46fSAndroid Build Coastguard Worker   pCJSRuntime->SetValueByNameInGlobalObject(szPropName, pValue);
290*3ac0a46fSAndroid Build Coastguard Worker }
291*3ac0a46fSAndroid Build Coastguard Worker 
292*3ac0a46fSAndroid Build Coastguard Worker // static
GlobalPropertyGetter(v8::Isolate * pIsolate,v8::Local<v8::Object> pObject,ByteStringView szPropName)293*3ac0a46fSAndroid Build Coastguard Worker v8::Local<v8::Value> CFXJSE_Engine::GlobalPropertyGetter(
294*3ac0a46fSAndroid Build Coastguard Worker     v8::Isolate* pIsolate,
295*3ac0a46fSAndroid Build Coastguard Worker     v8::Local<v8::Object> pObject,
296*3ac0a46fSAndroid Build Coastguard Worker     ByteStringView szPropName) {
297*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pOriginalObject = ToObject(pIsolate, pObject);
298*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Document* pDoc = pOriginalObject->GetDocument();
299*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Engine* pScriptContext = pDoc->GetScriptContext();
300*3ac0a46fSAndroid Build Coastguard Worker   WideString wsPropName = WideString::FromUTF8(szPropName);
301*3ac0a46fSAndroid Build Coastguard Worker 
302*3ac0a46fSAndroid Build Coastguard Worker   // Assume failure.
303*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Value> pValue = fxv8::NewUndefinedHelper(pIsolate);
304*3ac0a46fSAndroid Build Coastguard Worker 
305*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptContext->GetType() == CXFA_Script::Type::Formcalc) {
306*3ac0a46fSAndroid Build Coastguard Worker     if (szPropName == kFormCalcRuntime)
307*3ac0a46fSAndroid Build Coastguard Worker       return pScriptContext->m_FormCalcContext->GlobalPropertyGetter();
308*3ac0a46fSAndroid Build Coastguard Worker 
309*3ac0a46fSAndroid Build Coastguard Worker     XFA_HashCode uHashCode =
310*3ac0a46fSAndroid Build Coastguard Worker         static_cast<XFA_HashCode>(FX_HashCode_GetW(wsPropName.AsStringView()));
311*3ac0a46fSAndroid Build Coastguard Worker     if (uHashCode != XFA_HASHCODE_Layout) {
312*3ac0a46fSAndroid Build Coastguard Worker       CXFA_Object* pObj =
313*3ac0a46fSAndroid Build Coastguard Worker           pScriptContext->GetDocument()->GetXFAObject(uHashCode);
314*3ac0a46fSAndroid Build Coastguard Worker       if (pObj)
315*3ac0a46fSAndroid Build Coastguard Worker         return pScriptContext->GetOrCreateJSBindingFromMap(pObj);
316*3ac0a46fSAndroid Build Coastguard Worker     }
317*3ac0a46fSAndroid Build Coastguard Worker   }
318*3ac0a46fSAndroid Build Coastguard Worker 
319*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pRefNode = ToNode(pScriptContext->GetThisObject());
320*3ac0a46fSAndroid Build Coastguard Worker   if (pOriginalObject->IsThisProxy())
321*3ac0a46fSAndroid Build Coastguard Worker     pRefNode = ToNode(pScriptContext->GetVariablesThis(pOriginalObject));
322*3ac0a46fSAndroid Build Coastguard Worker 
323*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptContext->QueryNodeByFlag(
324*3ac0a46fSAndroid Build Coastguard Worker           pRefNode, wsPropName.AsStringView(), &pValue,
325*3ac0a46fSAndroid Build Coastguard Worker           Mask<XFA_ResolveFlag>{XFA_ResolveFlag::kChildren,
326*3ac0a46fSAndroid Build Coastguard Worker                                 XFA_ResolveFlag::kProperties,
327*3ac0a46fSAndroid Build Coastguard Worker                                 XFA_ResolveFlag::kAttributes})) {
328*3ac0a46fSAndroid Build Coastguard Worker     return pValue;
329*3ac0a46fSAndroid Build Coastguard Worker   }
330*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptContext->QueryNodeByFlag(
331*3ac0a46fSAndroid Build Coastguard Worker           pRefNode, wsPropName.AsStringView(), &pValue,
332*3ac0a46fSAndroid Build Coastguard Worker           Mask<XFA_ResolveFlag>{XFA_ResolveFlag::kParent,
333*3ac0a46fSAndroid Build Coastguard Worker                                 XFA_ResolveFlag::kSiblings})) {
334*3ac0a46fSAndroid Build Coastguard Worker     return pValue;
335*3ac0a46fSAndroid Build Coastguard Worker   }
336*3ac0a46fSAndroid Build Coastguard Worker 
337*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pScriptObject =
338*3ac0a46fSAndroid Build Coastguard Worker       pScriptContext->GetVariablesScript(pOriginalObject);
339*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptObject && pScriptContext->QueryVariableValue(
340*3ac0a46fSAndroid Build Coastguard Worker                            CXFA_Script::FromNode(pScriptObject->AsNode()),
341*3ac0a46fSAndroid Build Coastguard Worker                            szPropName, &pValue)) {
342*3ac0a46fSAndroid Build Coastguard Worker     return pValue;
343*3ac0a46fSAndroid Build Coastguard Worker   }
344*3ac0a46fSAndroid Build Coastguard Worker 
345*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = pDoc->GetNotify();
346*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
347*3ac0a46fSAndroid Build Coastguard Worker     return pValue;
348*3ac0a46fSAndroid Build Coastguard Worker 
349*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
350*3ac0a46fSAndroid Build Coastguard Worker   auto* pCJSRuntime = static_cast<CJS_Runtime*>(hDoc->GetIJSRuntime());
351*3ac0a46fSAndroid Build Coastguard Worker   if (!pCJSRuntime)
352*3ac0a46fSAndroid Build Coastguard Worker     return pValue;
353*3ac0a46fSAndroid Build Coastguard Worker 
354*3ac0a46fSAndroid Build Coastguard Worker   IJS_Runtime::ScopedEventContext pContext(pCJSRuntime);
355*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Value> temp_value =
356*3ac0a46fSAndroid Build Coastguard Worker       pCJSRuntime->GetValueByNameFromGlobalObject(szPropName);
357*3ac0a46fSAndroid Build Coastguard Worker 
358*3ac0a46fSAndroid Build Coastguard Worker   return !temp_value.IsEmpty() ? temp_value : pValue;
359*3ac0a46fSAndroid Build Coastguard Worker }
360*3ac0a46fSAndroid Build Coastguard Worker 
361*3ac0a46fSAndroid Build Coastguard Worker // static
GlobalPropTypeGetter(v8::Isolate * pIsolate,v8::Local<v8::Object> pHolder,ByteStringView szPropName,bool bQueryIn)362*3ac0a46fSAndroid Build Coastguard Worker FXJSE_ClassPropType CFXJSE_Engine::GlobalPropTypeGetter(
363*3ac0a46fSAndroid Build Coastguard Worker     v8::Isolate* pIsolate,
364*3ac0a46fSAndroid Build Coastguard Worker     v8::Local<v8::Object> pHolder,
365*3ac0a46fSAndroid Build Coastguard Worker     ByteStringView szPropName,
366*3ac0a46fSAndroid Build Coastguard Worker     bool bQueryIn) {
367*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pObject = ToObject(pIsolate, pHolder);
368*3ac0a46fSAndroid Build Coastguard Worker   if (!pObject)
369*3ac0a46fSAndroid Build Coastguard Worker     return FXJSE_ClassPropType::kNone;
370*3ac0a46fSAndroid Build Coastguard Worker 
371*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Engine* pScriptContext = pObject->GetDocument()->GetScriptContext();
372*3ac0a46fSAndroid Build Coastguard Worker   pObject = pScriptContext->GetVariablesThis(pObject);
373*3ac0a46fSAndroid Build Coastguard Worker   WideString wsPropName = WideString::FromUTF8(szPropName);
374*3ac0a46fSAndroid Build Coastguard Worker   if (pObject->JSObject()->HasMethod(wsPropName))
375*3ac0a46fSAndroid Build Coastguard Worker     return FXJSE_ClassPropType::kMethod;
376*3ac0a46fSAndroid Build Coastguard Worker 
377*3ac0a46fSAndroid Build Coastguard Worker   return FXJSE_ClassPropType::kProperty;
378*3ac0a46fSAndroid Build Coastguard Worker }
379*3ac0a46fSAndroid Build Coastguard Worker 
380*3ac0a46fSAndroid Build Coastguard Worker // static
NormalPropertyGetter(v8::Isolate * pIsolate,v8::Local<v8::Object> pHolder,ByteStringView szPropName)381*3ac0a46fSAndroid Build Coastguard Worker v8::Local<v8::Value> CFXJSE_Engine::NormalPropertyGetter(
382*3ac0a46fSAndroid Build Coastguard Worker     v8::Isolate* pIsolate,
383*3ac0a46fSAndroid Build Coastguard Worker     v8::Local<v8::Object> pHolder,
384*3ac0a46fSAndroid Build Coastguard Worker     ByteStringView szPropName) {
385*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pOriginalObject = ToObject(pIsolate, pHolder);
386*3ac0a46fSAndroid Build Coastguard Worker   if (!pOriginalObject)
387*3ac0a46fSAndroid Build Coastguard Worker     return fxv8::NewUndefinedHelper(pIsolate);
388*3ac0a46fSAndroid Build Coastguard Worker 
389*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Engine* pScriptContext =
390*3ac0a46fSAndroid Build Coastguard Worker       pOriginalObject->GetDocument()->GetScriptContext();
391*3ac0a46fSAndroid Build Coastguard Worker 
392*3ac0a46fSAndroid Build Coastguard Worker   WideString wsPropName = WideString::FromUTF8(szPropName);
393*3ac0a46fSAndroid Build Coastguard Worker   if (wsPropName.EqualsASCII("xfa")) {
394*3ac0a46fSAndroid Build Coastguard Worker     return pScriptContext->GetOrCreateJSBindingFromMap(
395*3ac0a46fSAndroid Build Coastguard Worker         pScriptContext->GetDocument()->GetRoot());
396*3ac0a46fSAndroid Build Coastguard Worker   }
397*3ac0a46fSAndroid Build Coastguard Worker 
398*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Value> pReturnValue = fxv8::NewUndefinedHelper(pIsolate);
399*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pObject = pScriptContext->GetVariablesThis(pOriginalObject);
400*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pRefNode = ToNode(pObject);
401*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptContext->QueryNodeByFlag(
402*3ac0a46fSAndroid Build Coastguard Worker           pRefNode, wsPropName.AsStringView(), &pReturnValue,
403*3ac0a46fSAndroid Build Coastguard Worker           Mask<XFA_ResolveFlag>{XFA_ResolveFlag::kChildren,
404*3ac0a46fSAndroid Build Coastguard Worker                                 XFA_ResolveFlag::kProperties,
405*3ac0a46fSAndroid Build Coastguard Worker                                 XFA_ResolveFlag::kAttributes})) {
406*3ac0a46fSAndroid Build Coastguard Worker     return pReturnValue;
407*3ac0a46fSAndroid Build Coastguard Worker   }
408*3ac0a46fSAndroid Build Coastguard Worker   if (pObject == pScriptContext->GetThisObject() ||
409*3ac0a46fSAndroid Build Coastguard Worker       (pScriptContext->GetType() == CXFA_Script::Type::Javascript &&
410*3ac0a46fSAndroid Build Coastguard Worker        !pScriptContext->IsStrictScopeInJavaScript())) {
411*3ac0a46fSAndroid Build Coastguard Worker     if (pScriptContext->QueryNodeByFlag(
412*3ac0a46fSAndroid Build Coastguard Worker             pRefNode, wsPropName.AsStringView(), &pReturnValue,
413*3ac0a46fSAndroid Build Coastguard Worker             Mask<XFA_ResolveFlag>{XFA_ResolveFlag::kParent,
414*3ac0a46fSAndroid Build Coastguard Worker                                   XFA_ResolveFlag::kSiblings})) {
415*3ac0a46fSAndroid Build Coastguard Worker       return pReturnValue;
416*3ac0a46fSAndroid Build Coastguard Worker     }
417*3ac0a46fSAndroid Build Coastguard Worker   }
418*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pScriptObject =
419*3ac0a46fSAndroid Build Coastguard Worker       pScriptContext->GetVariablesScript(pOriginalObject);
420*3ac0a46fSAndroid Build Coastguard Worker   if (!pScriptObject)
421*3ac0a46fSAndroid Build Coastguard Worker     return pReturnValue;
422*3ac0a46fSAndroid Build Coastguard Worker 
423*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptContext->QueryVariableValue(
424*3ac0a46fSAndroid Build Coastguard Worker           CXFA_Script::FromNode(pScriptObject->AsNode()), szPropName,
425*3ac0a46fSAndroid Build Coastguard Worker           &pReturnValue)) {
426*3ac0a46fSAndroid Build Coastguard Worker     return pReturnValue;
427*3ac0a46fSAndroid Build Coastguard Worker   }
428*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<XFA_SCRIPTATTRIBUTEINFO> info = XFA_GetScriptAttributeByName(
429*3ac0a46fSAndroid Build Coastguard Worker       pObject->GetElementType(), wsPropName.AsStringView());
430*3ac0a46fSAndroid Build Coastguard Worker   if (info.has_value()) {
431*3ac0a46fSAndroid Build Coastguard Worker     (*info.value().callback)(pIsolate, pObject->JSObject(), &pReturnValue,
432*3ac0a46fSAndroid Build Coastguard Worker                              false, info.value().attribute);
433*3ac0a46fSAndroid Build Coastguard Worker     return pReturnValue;
434*3ac0a46fSAndroid Build Coastguard Worker   }
435*3ac0a46fSAndroid Build Coastguard Worker 
436*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFNotify* pNotify = pObject->GetDocument()->GetNotify();
437*3ac0a46fSAndroid Build Coastguard Worker   if (!pNotify)
438*3ac0a46fSAndroid Build Coastguard Worker     return pReturnValue;
439*3ac0a46fSAndroid Build Coastguard Worker 
440*3ac0a46fSAndroid Build Coastguard Worker   CXFA_FFDoc* hDoc = pNotify->GetFFDoc();
441*3ac0a46fSAndroid Build Coastguard Worker   auto* pCJSRuntime = static_cast<CJS_Runtime*>(hDoc->GetIJSRuntime());
442*3ac0a46fSAndroid Build Coastguard Worker   if (!pCJSRuntime)
443*3ac0a46fSAndroid Build Coastguard Worker     return pReturnValue;
444*3ac0a46fSAndroid Build Coastguard Worker 
445*3ac0a46fSAndroid Build Coastguard Worker   IJS_Runtime::ScopedEventContext pContext(pCJSRuntime);
446*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Value> temp_local =
447*3ac0a46fSAndroid Build Coastguard Worker       pCJSRuntime->GetValueByNameFromGlobalObject(szPropName);
448*3ac0a46fSAndroid Build Coastguard Worker 
449*3ac0a46fSAndroid Build Coastguard Worker   return !temp_local.IsEmpty() ? temp_local : pReturnValue;
450*3ac0a46fSAndroid Build Coastguard Worker }
451*3ac0a46fSAndroid Build Coastguard Worker 
452*3ac0a46fSAndroid Build Coastguard Worker // static
NormalPropertySetter(v8::Isolate * pIsolate,v8::Local<v8::Object> pHolder,ByteStringView szPropName,v8::Local<v8::Value> pValue)453*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_Engine::NormalPropertySetter(v8::Isolate* pIsolate,
454*3ac0a46fSAndroid Build Coastguard Worker                                          v8::Local<v8::Object> pHolder,
455*3ac0a46fSAndroid Build Coastguard Worker                                          ByteStringView szPropName,
456*3ac0a46fSAndroid Build Coastguard Worker                                          v8::Local<v8::Value> pValue) {
457*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pOriginalObject = ToObject(pIsolate, pHolder);
458*3ac0a46fSAndroid Build Coastguard Worker   if (!pOriginalObject)
459*3ac0a46fSAndroid Build Coastguard Worker     return;
460*3ac0a46fSAndroid Build Coastguard Worker 
461*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Engine* pScriptContext =
462*3ac0a46fSAndroid Build Coastguard Worker       pOriginalObject->GetDocument()->GetScriptContext();
463*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptContext->IsResolvingNodes())
464*3ac0a46fSAndroid Build Coastguard Worker     return;
465*3ac0a46fSAndroid Build Coastguard Worker 
466*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pObject = pScriptContext->GetVariablesThis(pOriginalObject);
467*3ac0a46fSAndroid Build Coastguard Worker   WideString wsPropName = WideString::FromUTF8(szPropName);
468*3ac0a46fSAndroid Build Coastguard Worker   WideStringView wsPropNameView = wsPropName.AsStringView();
469*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<XFA_SCRIPTATTRIBUTEINFO> info =
470*3ac0a46fSAndroid Build Coastguard Worker       XFA_GetScriptAttributeByName(pObject->GetElementType(), wsPropNameView);
471*3ac0a46fSAndroid Build Coastguard Worker   if (info.has_value()) {
472*3ac0a46fSAndroid Build Coastguard Worker     CJX_Object* jsObject = pObject->JSObject();
473*3ac0a46fSAndroid Build Coastguard Worker     (*info.value().callback)(pIsolate, jsObject, &pValue, true,
474*3ac0a46fSAndroid Build Coastguard Worker                              info.value().attribute);
475*3ac0a46fSAndroid Build Coastguard Worker     return;
476*3ac0a46fSAndroid Build Coastguard Worker   }
477*3ac0a46fSAndroid Build Coastguard Worker 
478*3ac0a46fSAndroid Build Coastguard Worker   if (pObject->IsNode()) {
479*3ac0a46fSAndroid Build Coastguard Worker     if (wsPropNameView[0] == '#')
480*3ac0a46fSAndroid Build Coastguard Worker       wsPropNameView = wsPropNameView.Last(wsPropNameView.GetLength() - 1);
481*3ac0a46fSAndroid Build Coastguard Worker 
482*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pNode = ToNode(pObject);
483*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Node* pPropOrChild = nullptr;
484*3ac0a46fSAndroid Build Coastguard Worker     XFA_Element eType = XFA_GetElementByName(wsPropNameView);
485*3ac0a46fSAndroid Build Coastguard Worker     if (eType != XFA_Element::Unknown) {
486*3ac0a46fSAndroid Build Coastguard Worker       pPropOrChild =
487*3ac0a46fSAndroid Build Coastguard Worker           pNode->JSObject()->GetOrCreateProperty<CXFA_Node>(0, eType);
488*3ac0a46fSAndroid Build Coastguard Worker     } else {
489*3ac0a46fSAndroid Build Coastguard Worker       pPropOrChild = pNode->GetFirstChildByName(wsPropNameView);
490*3ac0a46fSAndroid Build Coastguard Worker     }
491*3ac0a46fSAndroid Build Coastguard Worker 
492*3ac0a46fSAndroid Build Coastguard Worker     if (pPropOrChild) {
493*3ac0a46fSAndroid Build Coastguard Worker       info = XFA_GetScriptAttributeByName(pPropOrChild->GetElementType(),
494*3ac0a46fSAndroid Build Coastguard Worker                                           L"{default}");
495*3ac0a46fSAndroid Build Coastguard Worker       if (info.has_value()) {
496*3ac0a46fSAndroid Build Coastguard Worker         pPropOrChild->JSObject()->ScriptSomDefaultValue(pIsolate, &pValue, true,
497*3ac0a46fSAndroid Build Coastguard Worker                                                         XFA_Attribute::Unknown);
498*3ac0a46fSAndroid Build Coastguard Worker         return;
499*3ac0a46fSAndroid Build Coastguard Worker       }
500*3ac0a46fSAndroid Build Coastguard Worker     }
501*3ac0a46fSAndroid Build Coastguard Worker   }
502*3ac0a46fSAndroid Build Coastguard Worker 
503*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pScriptObject =
504*3ac0a46fSAndroid Build Coastguard Worker       pScriptContext->GetVariablesScript(pOriginalObject);
505*3ac0a46fSAndroid Build Coastguard Worker   if (pScriptObject) {
506*3ac0a46fSAndroid Build Coastguard Worker     pScriptContext->UpdateVariableValue(
507*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Script::FromNode(pScriptObject->AsNode()), szPropName, pValue);
508*3ac0a46fSAndroid Build Coastguard Worker   }
509*3ac0a46fSAndroid Build Coastguard Worker }
510*3ac0a46fSAndroid Build Coastguard Worker 
NormalPropTypeGetter(v8::Isolate * pIsolate,v8::Local<v8::Object> pHolder,ByteStringView szPropName,bool bQueryIn)511*3ac0a46fSAndroid Build Coastguard Worker FXJSE_ClassPropType CFXJSE_Engine::NormalPropTypeGetter(
512*3ac0a46fSAndroid Build Coastguard Worker     v8::Isolate* pIsolate,
513*3ac0a46fSAndroid Build Coastguard Worker     v8::Local<v8::Object> pHolder,
514*3ac0a46fSAndroid Build Coastguard Worker     ByteStringView szPropName,
515*3ac0a46fSAndroid Build Coastguard Worker     bool bQueryIn) {
516*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pObject = ToObject(pIsolate, pHolder);
517*3ac0a46fSAndroid Build Coastguard Worker   if (!pObject)
518*3ac0a46fSAndroid Build Coastguard Worker     return FXJSE_ClassPropType::kNone;
519*3ac0a46fSAndroid Build Coastguard Worker 
520*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Engine* pScriptContext = pObject->GetDocument()->GetScriptContext();
521*3ac0a46fSAndroid Build Coastguard Worker   pObject = pScriptContext->GetVariablesThis(pObject);
522*3ac0a46fSAndroid Build Coastguard Worker   XFA_Element eType = pObject->GetElementType();
523*3ac0a46fSAndroid Build Coastguard Worker   WideString wsPropName = WideString::FromUTF8(szPropName);
524*3ac0a46fSAndroid Build Coastguard Worker   if (pObject->JSObject()->HasMethod(wsPropName))
525*3ac0a46fSAndroid Build Coastguard Worker     return FXJSE_ClassPropType::kMethod;
526*3ac0a46fSAndroid Build Coastguard Worker 
527*3ac0a46fSAndroid Build Coastguard Worker   if (bQueryIn) {
528*3ac0a46fSAndroid Build Coastguard Worker     absl::optional<XFA_SCRIPTATTRIBUTEINFO> maybe_info =
529*3ac0a46fSAndroid Build Coastguard Worker         XFA_GetScriptAttributeByName(eType, wsPropName.AsStringView());
530*3ac0a46fSAndroid Build Coastguard Worker     if (!maybe_info.has_value())
531*3ac0a46fSAndroid Build Coastguard Worker       return FXJSE_ClassPropType::kNone;
532*3ac0a46fSAndroid Build Coastguard Worker   }
533*3ac0a46fSAndroid Build Coastguard Worker   return FXJSE_ClassPropType::kProperty;
534*3ac0a46fSAndroid Build Coastguard Worker }
535*3ac0a46fSAndroid Build Coastguard Worker 
NormalMethodCall(const v8::FunctionCallbackInfo<v8::Value> & info,const WideString & functionName)536*3ac0a46fSAndroid Build Coastguard Worker CJS_Result CFXJSE_Engine::NormalMethodCall(
537*3ac0a46fSAndroid Build Coastguard Worker     const v8::FunctionCallbackInfo<v8::Value>& info,
538*3ac0a46fSAndroid Build Coastguard Worker     const WideString& functionName) {
539*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Object* pObject = ToObject(info);
540*3ac0a46fSAndroid Build Coastguard Worker   if (!pObject)
541*3ac0a46fSAndroid Build Coastguard Worker     return CJS_Result::Failure(L"no Holder() present.");
542*3ac0a46fSAndroid Build Coastguard Worker 
543*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Engine* pScriptContext = pObject->GetDocument()->GetScriptContext();
544*3ac0a46fSAndroid Build Coastguard Worker   pObject = pScriptContext->GetVariablesThis(pObject);
545*3ac0a46fSAndroid Build Coastguard Worker 
546*3ac0a46fSAndroid Build Coastguard Worker   std::vector<v8::Local<v8::Value>> parameters;
547*3ac0a46fSAndroid Build Coastguard Worker   for (int i = 0; i < info.Length(); i++)
548*3ac0a46fSAndroid Build Coastguard Worker     parameters.push_back(info[i]);
549*3ac0a46fSAndroid Build Coastguard Worker 
550*3ac0a46fSAndroid Build Coastguard Worker   return pObject->JSObject()->RunMethod(pScriptContext, functionName,
551*3ac0a46fSAndroid Build Coastguard Worker                                         parameters);
552*3ac0a46fSAndroid Build Coastguard Worker }
553*3ac0a46fSAndroid Build Coastguard Worker 
IsStrictScopeInJavaScript()554*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_Engine::IsStrictScopeInJavaScript() {
555*3ac0a46fSAndroid Build Coastguard Worker   return m_pDocument->is_strict_scoping();
556*3ac0a46fSAndroid Build Coastguard Worker }
557*3ac0a46fSAndroid Build Coastguard Worker 
GetType()558*3ac0a46fSAndroid Build Coastguard Worker CXFA_Script::Type CFXJSE_Engine::GetType() {
559*3ac0a46fSAndroid Build Coastguard Worker   return m_eScriptType;
560*3ac0a46fSAndroid Build Coastguard Worker }
561*3ac0a46fSAndroid Build Coastguard Worker 
AddObjectToUpArray(CXFA_Node * pNode)562*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_Engine::AddObjectToUpArray(CXFA_Node* pNode) {
563*3ac0a46fSAndroid Build Coastguard Worker   m_upObjectArray.push_back(pNode);
564*3ac0a46fSAndroid Build Coastguard Worker }
565*3ac0a46fSAndroid Build Coastguard Worker 
LastObjectFromUpArray()566*3ac0a46fSAndroid Build Coastguard Worker CXFA_Node* CFXJSE_Engine::LastObjectFromUpArray() {
567*3ac0a46fSAndroid Build Coastguard Worker   return !m_upObjectArray.empty() ? m_upObjectArray.back() : nullptr;
568*3ac0a46fSAndroid Build Coastguard Worker }
569*3ac0a46fSAndroid Build Coastguard Worker 
CreateVariablesContext(CXFA_Script * pScriptNode,CXFA_Node * pSubform)570*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Context* CFXJSE_Engine::CreateVariablesContext(CXFA_Script* pScriptNode,
571*3ac0a46fSAndroid Build Coastguard Worker                                                       CXFA_Node* pSubform) {
572*3ac0a46fSAndroid Build Coastguard Worker   if (!pScriptNode || !pSubform)
573*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
574*3ac0a46fSAndroid Build Coastguard Worker 
575*3ac0a46fSAndroid Build Coastguard Worker   auto* proxy = cppgc::MakeGarbageCollected<CXFA_ThisProxy>(
576*3ac0a46fSAndroid Build Coastguard Worker       pScriptNode->GetDocument()->GetHeap()->GetAllocationHandle(), pSubform,
577*3ac0a46fSAndroid Build Coastguard Worker       pScriptNode);
578*3ac0a46fSAndroid Build Coastguard Worker   auto pNewContext = CFXJSE_Context::Create(
579*3ac0a46fSAndroid Build Coastguard Worker       GetIsolate(), &kVariablesClassDescriptor, proxy->JSObject(), proxy);
580*3ac0a46fSAndroid Build Coastguard Worker   RemoveBuiltInObjs(pNewContext.get());
581*3ac0a46fSAndroid Build Coastguard Worker   pNewContext->EnableCompatibleMode();
582*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Context* pResult = pNewContext.get();
583*3ac0a46fSAndroid Build Coastguard Worker   m_mapVariableToContext[pScriptNode->JSObject()] = std::move(pNewContext);
584*3ac0a46fSAndroid Build Coastguard Worker   return pResult;
585*3ac0a46fSAndroid Build Coastguard Worker }
586*3ac0a46fSAndroid Build Coastguard Worker 
GetVariablesThis(CXFA_Object * pObject)587*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CFXJSE_Engine::GetVariablesThis(CXFA_Object* pObject) {
588*3ac0a46fSAndroid Build Coastguard Worker   CXFA_ThisProxy* pProxy = ToThisProxy(pObject);
589*3ac0a46fSAndroid Build Coastguard Worker   return pProxy ? pProxy->GetThisNode() : pObject;
590*3ac0a46fSAndroid Build Coastguard Worker }
591*3ac0a46fSAndroid Build Coastguard Worker 
GetVariablesScript(CXFA_Object * pObject)592*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CFXJSE_Engine::GetVariablesScript(CXFA_Object* pObject) {
593*3ac0a46fSAndroid Build Coastguard Worker   CXFA_ThisProxy* pProxy = ToThisProxy(pObject);
594*3ac0a46fSAndroid Build Coastguard Worker   return pProxy ? pProxy->GetScriptNode() : pObject;
595*3ac0a46fSAndroid Build Coastguard Worker }
596*3ac0a46fSAndroid Build Coastguard Worker 
RunVariablesScript(CXFA_Script * pScriptNode)597*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_Engine::RunVariablesScript(CXFA_Script* pScriptNode) {
598*3ac0a46fSAndroid Build Coastguard Worker   if (!pScriptNode)
599*3ac0a46fSAndroid Build Coastguard Worker     return;
600*3ac0a46fSAndroid Build Coastguard Worker 
601*3ac0a46fSAndroid Build Coastguard Worker   auto* pParent = CXFA_Variables::FromNode(pScriptNode->GetParent());
602*3ac0a46fSAndroid Build Coastguard Worker   if (!pParent)
603*3ac0a46fSAndroid Build Coastguard Worker     return;
604*3ac0a46fSAndroid Build Coastguard Worker 
605*3ac0a46fSAndroid Build Coastguard Worker   auto it = m_mapVariableToContext.find(pScriptNode->JSObject());
606*3ac0a46fSAndroid Build Coastguard Worker   if (it != m_mapVariableToContext.end() && it->second)
607*3ac0a46fSAndroid Build Coastguard Worker     return;
608*3ac0a46fSAndroid Build Coastguard Worker 
609*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pTextNode = pScriptNode->GetFirstChild();
610*3ac0a46fSAndroid Build Coastguard Worker   if (!pTextNode)
611*3ac0a46fSAndroid Build Coastguard Worker     return;
612*3ac0a46fSAndroid Build Coastguard Worker 
613*3ac0a46fSAndroid Build Coastguard Worker   absl::optional<WideString> wsScript =
614*3ac0a46fSAndroid Build Coastguard Worker       pTextNode->JSObject()->TryCData(XFA_Attribute::Value, true);
615*3ac0a46fSAndroid Build Coastguard Worker   if (!wsScript.has_value())
616*3ac0a46fSAndroid Build Coastguard Worker     return;
617*3ac0a46fSAndroid Build Coastguard Worker 
618*3ac0a46fSAndroid Build Coastguard Worker   ByteString btScript = wsScript->ToUTF8();
619*3ac0a46fSAndroid Build Coastguard Worker   auto hRetValue = std::make_unique<CFXJSE_Value>();
620*3ac0a46fSAndroid Build Coastguard Worker   CXFA_Node* pThisObject = pParent->GetParent();
621*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Context* pVariablesContext =
622*3ac0a46fSAndroid Build Coastguard Worker       CreateVariablesContext(pScriptNode, pThisObject);
623*3ac0a46fSAndroid Build Coastguard Worker   AutoRestorer<cppgc::Persistent<CXFA_Object>> nodeRestorer(&m_pThisObject);
624*3ac0a46fSAndroid Build Coastguard Worker   m_pThisObject = pThisObject;
625*3ac0a46fSAndroid Build Coastguard Worker   pVariablesContext->ExecuteScript(btScript.AsStringView(), hRetValue.get(),
626*3ac0a46fSAndroid Build Coastguard Worker                                    v8::Local<v8::Object>());
627*3ac0a46fSAndroid Build Coastguard Worker }
628*3ac0a46fSAndroid Build Coastguard Worker 
VariablesContextForScriptNode(CXFA_Script * pScriptNode)629*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Context* CFXJSE_Engine::VariablesContextForScriptNode(
630*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Script* pScriptNode) {
631*3ac0a46fSAndroid Build Coastguard Worker   if (!pScriptNode)
632*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
633*3ac0a46fSAndroid Build Coastguard Worker 
634*3ac0a46fSAndroid Build Coastguard Worker   auto* variablesNode = CXFA_Variables::FromNode(pScriptNode->GetParent());
635*3ac0a46fSAndroid Build Coastguard Worker   if (!variablesNode)
636*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
637*3ac0a46fSAndroid Build Coastguard Worker 
638*3ac0a46fSAndroid Build Coastguard Worker   auto it = m_mapVariableToContext.find(pScriptNode->JSObject());
639*3ac0a46fSAndroid Build Coastguard Worker   return it != m_mapVariableToContext.end() ? it->second.get() : nullptr;
640*3ac0a46fSAndroid Build Coastguard Worker }
641*3ac0a46fSAndroid Build Coastguard Worker 
QueryVariableValue(CXFA_Script * pScriptNode,ByteStringView szPropName,v8::Local<v8::Value> * pValue)642*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_Engine::QueryVariableValue(CXFA_Script* pScriptNode,
643*3ac0a46fSAndroid Build Coastguard Worker                                        ByteStringView szPropName,
644*3ac0a46fSAndroid Build Coastguard Worker                                        v8::Local<v8::Value>* pValue) {
645*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Context* pVariableContext = VariablesContextForScriptNode(pScriptNode);
646*3ac0a46fSAndroid Build Coastguard Worker   if (!pVariableContext)
647*3ac0a46fSAndroid Build Coastguard Worker     return false;
648*3ac0a46fSAndroid Build Coastguard Worker 
649*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Object> pObject = pVariableContext->GetGlobalObject();
650*3ac0a46fSAndroid Build Coastguard Worker   if (!fxv8::ReentrantHasObjectOwnPropertyHelper(GetIsolate(), pObject,
651*3ac0a46fSAndroid Build Coastguard Worker                                                  szPropName)) {
652*3ac0a46fSAndroid Build Coastguard Worker     return false;
653*3ac0a46fSAndroid Build Coastguard Worker   }
654*3ac0a46fSAndroid Build Coastguard Worker 
655*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Value> hVariableValue =
656*3ac0a46fSAndroid Build Coastguard Worker       fxv8::ReentrantGetObjectPropertyHelper(GetIsolate(), pObject, szPropName);
657*3ac0a46fSAndroid Build Coastguard Worker   if (fxv8::IsFunction(hVariableValue)) {
658*3ac0a46fSAndroid Build Coastguard Worker     v8::Local<v8::Function> maybeFunc = CFXJSE_Value::NewBoundFunction(
659*3ac0a46fSAndroid Build Coastguard Worker         GetIsolate(), hVariableValue.As<v8::Function>(), pObject);
660*3ac0a46fSAndroid Build Coastguard Worker     if (!maybeFunc.IsEmpty())
661*3ac0a46fSAndroid Build Coastguard Worker       *pValue = maybeFunc;
662*3ac0a46fSAndroid Build Coastguard Worker   } else {
663*3ac0a46fSAndroid Build Coastguard Worker     *pValue = hVariableValue;
664*3ac0a46fSAndroid Build Coastguard Worker   }
665*3ac0a46fSAndroid Build Coastguard Worker   return true;
666*3ac0a46fSAndroid Build Coastguard Worker }
667*3ac0a46fSAndroid Build Coastguard Worker 
UpdateVariableValue(CXFA_Script * pScriptNode,ByteStringView szPropName,v8::Local<v8::Value> pValue)668*3ac0a46fSAndroid Build Coastguard Worker bool CFXJSE_Engine::UpdateVariableValue(CXFA_Script* pScriptNode,
669*3ac0a46fSAndroid Build Coastguard Worker                                         ByteStringView szPropName,
670*3ac0a46fSAndroid Build Coastguard Worker                                         v8::Local<v8::Value> pValue) {
671*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_Context* pVariableContext = VariablesContextForScriptNode(pScriptNode);
672*3ac0a46fSAndroid Build Coastguard Worker   if (!pVariableContext)
673*3ac0a46fSAndroid Build Coastguard Worker     return false;
674*3ac0a46fSAndroid Build Coastguard Worker 
675*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Object> pObject = pVariableContext->GetGlobalObject();
676*3ac0a46fSAndroid Build Coastguard Worker   fxv8::ReentrantSetObjectOwnPropertyHelper(GetIsolate(), pObject, szPropName,
677*3ac0a46fSAndroid Build Coastguard Worker                                             pValue);
678*3ac0a46fSAndroid Build Coastguard Worker   return true;
679*3ac0a46fSAndroid Build Coastguard Worker }
680*3ac0a46fSAndroid Build Coastguard Worker 
RemoveBuiltInObjs(CFXJSE_Context * pContext)681*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_Engine::RemoveBuiltInObjs(CFXJSE_Context* pContext) {
682*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
683*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Object> pObject = pContext->GetGlobalObject();
684*3ac0a46fSAndroid Build Coastguard Worker   fxv8::ReentrantDeleteObjectPropertyHelper(GetIsolate(), pObject, "Number");
685*3ac0a46fSAndroid Build Coastguard Worker   fxv8::ReentrantDeleteObjectPropertyHelper(GetIsolate(), pObject, "Date");
686*3ac0a46fSAndroid Build Coastguard Worker }
687*3ac0a46fSAndroid Build Coastguard Worker 
ResolveObjects(CXFA_Object * refObject,WideStringView wsExpression,Mask<XFA_ResolveFlag> dwStyles)688*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFXJSE_Engine::ResolveResult> CFXJSE_Engine::ResolveObjects(
689*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Object* refObject,
690*3ac0a46fSAndroid Build Coastguard Worker     WideStringView wsExpression,
691*3ac0a46fSAndroid Build Coastguard Worker     Mask<XFA_ResolveFlag> dwStyles) {
692*3ac0a46fSAndroid Build Coastguard Worker   return ResolveObjectsWithBindNode(refObject, wsExpression, dwStyles, nullptr);
693*3ac0a46fSAndroid Build Coastguard Worker }
694*3ac0a46fSAndroid Build Coastguard Worker 
695*3ac0a46fSAndroid Build Coastguard Worker absl::optional<CFXJSE_Engine::ResolveResult>
ResolveObjectsWithBindNode(CXFA_Object * refObject,WideStringView wsExpression,Mask<XFA_ResolveFlag> dwStyles,CXFA_Node * bindNode)696*3ac0a46fSAndroid Build Coastguard Worker CFXJSE_Engine::ResolveObjectsWithBindNode(CXFA_Object* refObject,
697*3ac0a46fSAndroid Build Coastguard Worker                                           WideStringView wsExpression,
698*3ac0a46fSAndroid Build Coastguard Worker                                           Mask<XFA_ResolveFlag> dwStyles,
699*3ac0a46fSAndroid Build Coastguard Worker                                           CXFA_Node* bindNode) {
700*3ac0a46fSAndroid Build Coastguard Worker   if (wsExpression.IsEmpty())
701*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
702*3ac0a46fSAndroid Build Coastguard Worker 
703*3ac0a46fSAndroid Build Coastguard Worker   AutoRestorer<bool> resolving_restorer(&m_bResolvingNodes);
704*3ac0a46fSAndroid Build Coastguard Worker   m_bResolvingNodes = true;
705*3ac0a46fSAndroid Build Coastguard Worker 
706*3ac0a46fSAndroid Build Coastguard Worker   const bool bParentOrSiblings =
707*3ac0a46fSAndroid Build Coastguard Worker       !!(dwStyles & Mask<XFA_ResolveFlag>{XFA_ResolveFlag::kParent,
708*3ac0a46fSAndroid Build Coastguard Worker                                           XFA_ResolveFlag::kSiblings});
709*3ac0a46fSAndroid Build Coastguard Worker   if (m_eScriptType != CXFA_Script::Type::Formcalc || bParentOrSiblings)
710*3ac0a46fSAndroid Build Coastguard Worker     m_upObjectArray.clear();
711*3ac0a46fSAndroid Build Coastguard Worker   if (refObject && refObject->IsNode() && bParentOrSiblings)
712*3ac0a46fSAndroid Build Coastguard Worker     m_upObjectArray.push_back(refObject->AsNode());
713*3ac0a46fSAndroid Build Coastguard Worker 
714*3ac0a46fSAndroid Build Coastguard Worker   ResolveResult result;
715*3ac0a46fSAndroid Build Coastguard Worker   bool bNextCreate = false;
716*3ac0a46fSAndroid Build Coastguard Worker   if (dwStyles & XFA_ResolveFlag::kCreateNode)
717*3ac0a46fSAndroid Build Coastguard Worker     m_NodeHelper->SetCreateNodeType(bindNode);
718*3ac0a46fSAndroid Build Coastguard Worker 
719*3ac0a46fSAndroid Build Coastguard Worker   m_NodeHelper->m_pCreateParent = nullptr;
720*3ac0a46fSAndroid Build Coastguard Worker   m_NodeHelper->m_iCurAllStart = -1;
721*3ac0a46fSAndroid Build Coastguard Worker 
722*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_ResolveProcessor::NodeData rndFind;
723*3ac0a46fSAndroid Build Coastguard Worker   int32_t nStart = 0;
724*3ac0a46fSAndroid Build Coastguard Worker   int32_t nLevel = 0;
725*3ac0a46fSAndroid Build Coastguard Worker 
726*3ac0a46fSAndroid Build Coastguard Worker   std::vector<cppgc::Member<CXFA_Object>> findObjects;
727*3ac0a46fSAndroid Build Coastguard Worker   findObjects.emplace_back(refObject ? refObject : m_pDocument->GetRoot());
728*3ac0a46fSAndroid Build Coastguard Worker   int32_t nNodes = 0;
729*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_ScopeUtil_IsolateHandleContext scope(GetJseContext());
730*3ac0a46fSAndroid Build Coastguard Worker   while (true) {
731*3ac0a46fSAndroid Build Coastguard Worker     nNodes = fxcrt::CollectionSize<int32_t>(findObjects);
732*3ac0a46fSAndroid Build Coastguard Worker     int32_t i = 0;
733*3ac0a46fSAndroid Build Coastguard Worker     rndFind.m_dwStyles = dwStyles;
734*3ac0a46fSAndroid Build Coastguard Worker     m_ResolveProcessor->SetCurStart(nStart);
735*3ac0a46fSAndroid Build Coastguard Worker     nStart = m_ResolveProcessor->GetFilter(wsExpression, nStart, rndFind);
736*3ac0a46fSAndroid Build Coastguard Worker     if (nStart < 1) {
737*3ac0a46fSAndroid Build Coastguard Worker       if ((dwStyles & XFA_ResolveFlag::kCreateNode) && !bNextCreate) {
738*3ac0a46fSAndroid Build Coastguard Worker         CXFA_Node* pDataNode = nullptr;
739*3ac0a46fSAndroid Build Coastguard Worker         nStart = m_NodeHelper->m_iCurAllStart;
740*3ac0a46fSAndroid Build Coastguard Worker         if (nStart != -1) {
741*3ac0a46fSAndroid Build Coastguard Worker           pDataNode = m_pDocument->GetNotBindNode(findObjects);
742*3ac0a46fSAndroid Build Coastguard Worker           if (pDataNode) {
743*3ac0a46fSAndroid Build Coastguard Worker             findObjects.clear();
744*3ac0a46fSAndroid Build Coastguard Worker             findObjects.emplace_back(pDataNode);
745*3ac0a46fSAndroid Build Coastguard Worker             break;
746*3ac0a46fSAndroid Build Coastguard Worker           }
747*3ac0a46fSAndroid Build Coastguard Worker         } else {
748*3ac0a46fSAndroid Build Coastguard Worker           pDataNode = findObjects.front()->AsNode();
749*3ac0a46fSAndroid Build Coastguard Worker           findObjects.clear();
750*3ac0a46fSAndroid Build Coastguard Worker           findObjects.emplace_back(pDataNode);
751*3ac0a46fSAndroid Build Coastguard Worker           break;
752*3ac0a46fSAndroid Build Coastguard Worker         }
753*3ac0a46fSAndroid Build Coastguard Worker         dwStyles |= XFA_ResolveFlag::kBind;
754*3ac0a46fSAndroid Build Coastguard Worker         findObjects.clear();
755*3ac0a46fSAndroid Build Coastguard Worker         findObjects.emplace_back(m_NodeHelper->m_pAllStartParent.Get());
756*3ac0a46fSAndroid Build Coastguard Worker         continue;
757*3ac0a46fSAndroid Build Coastguard Worker       }
758*3ac0a46fSAndroid Build Coastguard Worker       break;
759*3ac0a46fSAndroid Build Coastguard Worker     }
760*3ac0a46fSAndroid Build Coastguard Worker     if (bNextCreate) {
761*3ac0a46fSAndroid Build Coastguard Worker       int32_t checked_length =
762*3ac0a46fSAndroid Build Coastguard Worker           pdfium::base::checked_cast<int32_t>(wsExpression.GetLength());
763*3ac0a46fSAndroid Build Coastguard Worker       if (m_NodeHelper->CreateNode(rndFind.m_wsName, rndFind.m_wsCondition,
764*3ac0a46fSAndroid Build Coastguard Worker                                    nStart == checked_length, this)) {
765*3ac0a46fSAndroid Build Coastguard Worker         continue;
766*3ac0a46fSAndroid Build Coastguard Worker       }
767*3ac0a46fSAndroid Build Coastguard Worker       break;
768*3ac0a46fSAndroid Build Coastguard Worker     }
769*3ac0a46fSAndroid Build Coastguard Worker     std::vector<cppgc::Member<CXFA_Object>> retObjects;
770*3ac0a46fSAndroid Build Coastguard Worker     while (i < nNodes) {
771*3ac0a46fSAndroid Build Coastguard Worker       bool bDataBind = false;
772*3ac0a46fSAndroid Build Coastguard Worker       if (((dwStyles & XFA_ResolveFlag::kBind) ||
773*3ac0a46fSAndroid Build Coastguard Worker            (dwStyles & XFA_ResolveFlag::kCreateNode)) &&
774*3ac0a46fSAndroid Build Coastguard Worker           nNodes > 1) {
775*3ac0a46fSAndroid Build Coastguard Worker         CFXJSE_ResolveProcessor::NodeData rndBind;
776*3ac0a46fSAndroid Build Coastguard Worker         m_ResolveProcessor->GetFilter(wsExpression, nStart, rndBind);
777*3ac0a46fSAndroid Build Coastguard Worker         i = m_ResolveProcessor->IndexForDataBind(rndBind.m_wsCondition, nNodes);
778*3ac0a46fSAndroid Build Coastguard Worker         bDataBind = true;
779*3ac0a46fSAndroid Build Coastguard Worker       }
780*3ac0a46fSAndroid Build Coastguard Worker       rndFind.m_CurObject = findObjects[i++].Get();
781*3ac0a46fSAndroid Build Coastguard Worker       rndFind.m_nLevel = nLevel;
782*3ac0a46fSAndroid Build Coastguard Worker       rndFind.m_Result.type = ResolveResult::Type::kNodes;
783*3ac0a46fSAndroid Build Coastguard Worker       if (!m_ResolveProcessor->Resolve(GetIsolate(), rndFind))
784*3ac0a46fSAndroid Build Coastguard Worker         continue;
785*3ac0a46fSAndroid Build Coastguard Worker 
786*3ac0a46fSAndroid Build Coastguard Worker       if (rndFind.m_Result.type == ResolveResult::Type::kAttribute &&
787*3ac0a46fSAndroid Build Coastguard Worker           rndFind.m_Result.script_attribute.callback &&
788*3ac0a46fSAndroid Build Coastguard Worker           nStart <
789*3ac0a46fSAndroid Build Coastguard Worker               pdfium::base::checked_cast<int32_t>(wsExpression.GetLength())) {
790*3ac0a46fSAndroid Build Coastguard Worker         v8::Local<v8::Value> pValue;
791*3ac0a46fSAndroid Build Coastguard Worker         CJX_Object* jsObject = rndFind.m_Result.objects.front()->JSObject();
792*3ac0a46fSAndroid Build Coastguard Worker         (*rndFind.m_Result.script_attribute.callback)(
793*3ac0a46fSAndroid Build Coastguard Worker             GetIsolate(), jsObject, &pValue, false,
794*3ac0a46fSAndroid Build Coastguard Worker             rndFind.m_Result.script_attribute.attribute);
795*3ac0a46fSAndroid Build Coastguard Worker         if (!pValue.IsEmpty()) {
796*3ac0a46fSAndroid Build Coastguard Worker           rndFind.m_Result.objects.front() = ToObject(GetIsolate(), pValue);
797*3ac0a46fSAndroid Build Coastguard Worker         }
798*3ac0a46fSAndroid Build Coastguard Worker       }
799*3ac0a46fSAndroid Build Coastguard Worker       if (!m_upObjectArray.empty())
800*3ac0a46fSAndroid Build Coastguard Worker         m_upObjectArray.pop_back();
801*3ac0a46fSAndroid Build Coastguard Worker       retObjects.insert(retObjects.end(), rndFind.m_Result.objects.begin(),
802*3ac0a46fSAndroid Build Coastguard Worker                         rndFind.m_Result.objects.end());
803*3ac0a46fSAndroid Build Coastguard Worker       rndFind.m_Result.objects.clear();
804*3ac0a46fSAndroid Build Coastguard Worker       if (bDataBind)
805*3ac0a46fSAndroid Build Coastguard Worker         break;
806*3ac0a46fSAndroid Build Coastguard Worker     }
807*3ac0a46fSAndroid Build Coastguard Worker     findObjects.clear();
808*3ac0a46fSAndroid Build Coastguard Worker 
809*3ac0a46fSAndroid Build Coastguard Worker     nNodes = fxcrt::CollectionSize<int32_t>(retObjects);
810*3ac0a46fSAndroid Build Coastguard Worker     if (nNodes < 1) {
811*3ac0a46fSAndroid Build Coastguard Worker       if (dwStyles & XFA_ResolveFlag::kCreateNode) {
812*3ac0a46fSAndroid Build Coastguard Worker         bNextCreate = true;
813*3ac0a46fSAndroid Build Coastguard Worker         if (!m_NodeHelper->m_pCreateParent) {
814*3ac0a46fSAndroid Build Coastguard Worker           m_NodeHelper->m_pCreateParent = ToNode(rndFind.m_CurObject);
815*3ac0a46fSAndroid Build Coastguard Worker           m_NodeHelper->m_iCreateCount = 1;
816*3ac0a46fSAndroid Build Coastguard Worker         }
817*3ac0a46fSAndroid Build Coastguard Worker         int32_t checked_length =
818*3ac0a46fSAndroid Build Coastguard Worker             pdfium::base::checked_cast<int32_t>(wsExpression.GetLength());
819*3ac0a46fSAndroid Build Coastguard Worker         if (m_NodeHelper->CreateNode(rndFind.m_wsName, rndFind.m_wsCondition,
820*3ac0a46fSAndroid Build Coastguard Worker                                      nStart == checked_length, this)) {
821*3ac0a46fSAndroid Build Coastguard Worker           continue;
822*3ac0a46fSAndroid Build Coastguard Worker         }
823*3ac0a46fSAndroid Build Coastguard Worker       }
824*3ac0a46fSAndroid Build Coastguard Worker       break;
825*3ac0a46fSAndroid Build Coastguard Worker     }
826*3ac0a46fSAndroid Build Coastguard Worker 
827*3ac0a46fSAndroid Build Coastguard Worker     findObjects = std::move(retObjects);
828*3ac0a46fSAndroid Build Coastguard Worker     rndFind.m_Result.objects.clear();
829*3ac0a46fSAndroid Build Coastguard Worker     if (nLevel == 0) {
830*3ac0a46fSAndroid Build Coastguard Worker       dwStyles.Clear(XFA_ResolveFlag::kParent);
831*3ac0a46fSAndroid Build Coastguard Worker       dwStyles.Clear(XFA_ResolveFlag::kSiblings);
832*3ac0a46fSAndroid Build Coastguard Worker     }
833*3ac0a46fSAndroid Build Coastguard Worker     nLevel++;
834*3ac0a46fSAndroid Build Coastguard Worker   }
835*3ac0a46fSAndroid Build Coastguard Worker 
836*3ac0a46fSAndroid Build Coastguard Worker   if (!bNextCreate) {
837*3ac0a46fSAndroid Build Coastguard Worker     result.type = rndFind.m_Result.type;
838*3ac0a46fSAndroid Build Coastguard Worker     if (nNodes > 0) {
839*3ac0a46fSAndroid Build Coastguard Worker       result.objects.insert(result.objects.end(), findObjects.begin(),
840*3ac0a46fSAndroid Build Coastguard Worker                             findObjects.end());
841*3ac0a46fSAndroid Build Coastguard Worker     }
842*3ac0a46fSAndroid Build Coastguard Worker     if (rndFind.m_Result.type == ResolveResult::Type::kAttribute) {
843*3ac0a46fSAndroid Build Coastguard Worker       result.script_attribute = rndFind.m_Result.script_attribute;
844*3ac0a46fSAndroid Build Coastguard Worker       return result;
845*3ac0a46fSAndroid Build Coastguard Worker     }
846*3ac0a46fSAndroid Build Coastguard Worker   }
847*3ac0a46fSAndroid Build Coastguard Worker   if ((dwStyles & XFA_ResolveFlag::kCreateNode) ||
848*3ac0a46fSAndroid Build Coastguard Worker       (dwStyles & XFA_ResolveFlag::kBind) ||
849*3ac0a46fSAndroid Build Coastguard Worker       (dwStyles & XFA_ResolveFlag::kBindNew)) {
850*3ac0a46fSAndroid Build Coastguard Worker     if (m_NodeHelper->m_pCreateParent)
851*3ac0a46fSAndroid Build Coastguard Worker       result.objects.emplace_back(m_NodeHelper->m_pCreateParent.Get());
852*3ac0a46fSAndroid Build Coastguard Worker     else
853*3ac0a46fSAndroid Build Coastguard Worker       m_NodeHelper->CreateNodeForCondition(rndFind.m_wsCondition);
854*3ac0a46fSAndroid Build Coastguard Worker 
855*3ac0a46fSAndroid Build Coastguard Worker     result.type = m_NodeHelper->m_iCreateFlag;
856*3ac0a46fSAndroid Build Coastguard Worker     if (result.type == ResolveResult::Type::kCreateNodeOne) {
857*3ac0a46fSAndroid Build Coastguard Worker       if (m_NodeHelper->m_iCurAllStart != -1)
858*3ac0a46fSAndroid Build Coastguard Worker         result.type = ResolveResult::Type::kCreateNodeMidAll;
859*3ac0a46fSAndroid Build Coastguard Worker     }
860*3ac0a46fSAndroid Build Coastguard Worker 
861*3ac0a46fSAndroid Build Coastguard Worker     if (!bNextCreate && (dwStyles & XFA_ResolveFlag::kCreateNode))
862*3ac0a46fSAndroid Build Coastguard Worker       result.type = ResolveResult::Type::kExistNodes;
863*3ac0a46fSAndroid Build Coastguard Worker 
864*3ac0a46fSAndroid Build Coastguard Worker     if (result.objects.empty())
865*3ac0a46fSAndroid Build Coastguard Worker       return absl::nullopt;
866*3ac0a46fSAndroid Build Coastguard Worker 
867*3ac0a46fSAndroid Build Coastguard Worker     return result;
868*3ac0a46fSAndroid Build Coastguard Worker   }
869*3ac0a46fSAndroid Build Coastguard Worker   if (nNodes == 0)
870*3ac0a46fSAndroid Build Coastguard Worker     return absl::nullopt;
871*3ac0a46fSAndroid Build Coastguard Worker 
872*3ac0a46fSAndroid Build Coastguard Worker   return result;
873*3ac0a46fSAndroid Build Coastguard Worker }
874*3ac0a46fSAndroid Build Coastguard Worker 
GetOrCreateJSBindingFromMap(CXFA_Object * pObject)875*3ac0a46fSAndroid Build Coastguard Worker v8::Local<v8::Object> CFXJSE_Engine::GetOrCreateJSBindingFromMap(
876*3ac0a46fSAndroid Build Coastguard Worker     CXFA_Object* pObject) {
877*3ac0a46fSAndroid Build Coastguard Worker   RunVariablesScript(CXFA_Script::FromNode(pObject->AsNode()));
878*3ac0a46fSAndroid Build Coastguard Worker 
879*3ac0a46fSAndroid Build Coastguard Worker   CJX_Object* pCJXObject = pObject->JSObject();
880*3ac0a46fSAndroid Build Coastguard Worker   auto iter = m_mapObjectToObject.find(pCJXObject);
881*3ac0a46fSAndroid Build Coastguard Worker   if (iter != m_mapObjectToObject.end())
882*3ac0a46fSAndroid Build Coastguard Worker     return v8::Local<v8::Object>::New(GetIsolate(), iter->second);
883*3ac0a46fSAndroid Build Coastguard Worker 
884*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Object> binding = pCJXObject->NewBoundV8Object(
885*3ac0a46fSAndroid Build Coastguard Worker       GetIsolate(), m_pJsClass->GetTemplate(GetIsolate()));
886*3ac0a46fSAndroid Build Coastguard Worker 
887*3ac0a46fSAndroid Build Coastguard Worker   m_mapObjectToObject[pCJXObject].Reset(GetIsolate(), binding);
888*3ac0a46fSAndroid Build Coastguard Worker   return binding;
889*3ac0a46fSAndroid Build Coastguard Worker }
890*3ac0a46fSAndroid Build Coastguard Worker 
SetNodesOfRunScript(std::vector<cppgc::Persistent<CXFA_Node>> * pArray)891*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_Engine::SetNodesOfRunScript(
892*3ac0a46fSAndroid Build Coastguard Worker     std::vector<cppgc::Persistent<CXFA_Node>>* pArray) {
893*3ac0a46fSAndroid Build Coastguard Worker   m_pScriptNodeArray = pArray;
894*3ac0a46fSAndroid Build Coastguard Worker }
895*3ac0a46fSAndroid Build Coastguard Worker 
AddNodesOfRunScript(CXFA_Node * pNode)896*3ac0a46fSAndroid Build Coastguard Worker void CFXJSE_Engine::AddNodesOfRunScript(CXFA_Node* pNode) {
897*3ac0a46fSAndroid Build Coastguard Worker   if (m_pScriptNodeArray && !pdfium::Contains(*m_pScriptNodeArray, pNode))
898*3ac0a46fSAndroid Build Coastguard Worker     m_pScriptNodeArray->emplace_back(pNode);
899*3ac0a46fSAndroid Build Coastguard Worker }
900*3ac0a46fSAndroid Build Coastguard Worker 
ToXFAObject(v8::Local<v8::Value> obj)901*3ac0a46fSAndroid Build Coastguard Worker CXFA_Object* CFXJSE_Engine::ToXFAObject(v8::Local<v8::Value> obj) {
902*3ac0a46fSAndroid Build Coastguard Worker   if (!fxv8::IsObject(obj))
903*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
904*3ac0a46fSAndroid Build Coastguard Worker 
905*3ac0a46fSAndroid Build Coastguard Worker   CFXJSE_HostObject* pHostObj =
906*3ac0a46fSAndroid Build Coastguard Worker       FXJSE_RetrieveObjectBinding(obj.As<v8::Object>());
907*3ac0a46fSAndroid Build Coastguard Worker   if (!pHostObj)
908*3ac0a46fSAndroid Build Coastguard Worker     return nullptr;
909*3ac0a46fSAndroid Build Coastguard Worker 
910*3ac0a46fSAndroid Build Coastguard Worker   CJX_Object* pJSObject = pHostObj->AsCJXObject();
911*3ac0a46fSAndroid Build Coastguard Worker   return pJSObject ? pJSObject->GetXFAObject() : nullptr;
912*3ac0a46fSAndroid Build Coastguard Worker }
913*3ac0a46fSAndroid Build Coastguard Worker 
NewNormalXFAObject(CXFA_Object * obj)914*3ac0a46fSAndroid Build Coastguard Worker v8::Local<v8::Object> CFXJSE_Engine::NewNormalXFAObject(CXFA_Object* obj) {
915*3ac0a46fSAndroid Build Coastguard Worker   v8::EscapableHandleScope scope(GetIsolate());
916*3ac0a46fSAndroid Build Coastguard Worker   v8::Local<v8::Object> object = obj->JSObject()->NewBoundV8Object(
917*3ac0a46fSAndroid Build Coastguard Worker       GetIsolate(), GetJseNormalClass()->GetTemplate(GetIsolate()));
918*3ac0a46fSAndroid Build Coastguard Worker   return scope.Escape(object);
919*3ac0a46fSAndroid Build Coastguard Worker }
920