• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "fxjs/cjs_global.h"
8 
9 #include <map>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "core/fxcrt/fx_extension.h"
15 #include "fxjs/JS_Define.h"
16 #include "fxjs/cjs_event_context.h"
17 #include "fxjs/cjs_eventhandler.h"
18 #include "fxjs/cjs_globaldata.h"
19 #include "fxjs/cjs_keyvalue.h"
20 #include "fxjs/cjs_object.h"
21 #include "fxjs/js_resources.h"
22 
23 namespace {
24 
PropFromV8Prop(v8::Isolate * pIsolate,v8::Local<v8::String> property)25 WideString PropFromV8Prop(v8::Isolate* pIsolate,
26                           v8::Local<v8::String> property) {
27   v8::String::Utf8Value utf8_value(pIsolate, property);
28   return WideString::FromUTF8(ByteStringView(*utf8_value, utf8_value.length()));
29 }
30 
31 template <class Alt>
JSSpecialPropQuery(const char *,v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Integer> & info)32 void JSSpecialPropQuery(const char*,
33                         v8::Local<v8::String> property,
34                         const v8::PropertyCallbackInfo<v8::Integer>& info) {
35   CJS_Runtime* pRuntime =
36       CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
37   if (!pRuntime)
38     return;
39 
40   CJS_Object* pJSObj =
41       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
42   if (!pJSObj)
43     return;
44 
45   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
46   CJS_Return result =
47       pObj->QueryProperty(PropFromV8Prop(info.GetIsolate(), property).c_str());
48   info.GetReturnValue().Set(!result.HasError() ? 4 : 0);
49 }
50 
51 template <class Alt>
JSSpecialPropGet(const char * class_name,v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)52 void JSSpecialPropGet(const char* class_name,
53                       v8::Local<v8::String> property,
54                       const v8::PropertyCallbackInfo<v8::Value>& info) {
55   CJS_Runtime* pRuntime =
56       CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
57   if (!pRuntime)
58     return;
59 
60   CJS_Object* pJSObj =
61       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
62   if (!pJSObj)
63     return;
64 
65   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
66   CJS_Return result = pObj->GetProperty(
67       pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str());
68   if (result.HasError()) {
69     pRuntime->Error(
70         JSFormatErrorString(class_name, "GetProperty", result.Error()));
71     return;
72   }
73 
74   if (result.HasReturn())
75     info.GetReturnValue().Set(result.Return());
76 }
77 
78 template <class Alt>
JSSpecialPropPut(const char * class_name,v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value> & info)79 void JSSpecialPropPut(const char* class_name,
80                       v8::Local<v8::String> property,
81                       v8::Local<v8::Value> value,
82                       const v8::PropertyCallbackInfo<v8::Value>& info) {
83   CJS_Runtime* pRuntime =
84       CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
85   if (!pRuntime)
86     return;
87 
88   CJS_Object* pJSObj =
89       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
90   if (!pJSObj)
91     return;
92 
93   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
94   CJS_Return result = pObj->SetProperty(
95       pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str(), value);
96   if (result.HasError()) {
97     pRuntime->Error(
98         JSFormatErrorString(class_name, "PutProperty", result.Error()));
99   }
100 }
101 
102 template <class Alt>
JSSpecialPropDel(const char * class_name,v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Boolean> & info)103 void JSSpecialPropDel(const char* class_name,
104                       v8::Local<v8::String> property,
105                       const v8::PropertyCallbackInfo<v8::Boolean>& info) {
106   CJS_Runtime* pRuntime =
107       CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
108   if (!pRuntime)
109     return;
110 
111   CJS_Object* pJSObj =
112       static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
113   if (!pJSObj)
114     return;
115 
116   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
117   CJS_Return result = pObj->DelProperty(
118       pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str());
119   if (result.HasError()) {
120     // TODO(dsinclair): Should this set the pRuntime->Error result?
121     // ByteString cbName =
122     //     ByteString::Format("%s.%s", class_name, "DelProperty");
123   }
124 }
125 
126 struct JSGlobalData {
127   JSGlobalData();
128   ~JSGlobalData();
129 
130   JS_GlobalDataType nType;
131   double dData;
132   bool bData;
133   ByteString sData;
134   v8::Global<v8::Object> pData;
135   bool bPersistent;
136   bool bDeleted;
137 };
138 
139 class JSGlobalAlternate : public CJS_EmbedObj {
140  public:
141   explicit JSGlobalAlternate(CJS_Object* pJSObject);
142   ~JSGlobalAlternate() override;
143 
144   CJS_Return setPersistent(CJS_Runtime* pRuntime,
145                            const std::vector<v8::Local<v8::Value>>& params);
146   CJS_Return QueryProperty(const wchar_t* propname);
147   CJS_Return GetProperty(CJS_Runtime* pRuntime, const wchar_t* propname);
148   CJS_Return SetProperty(CJS_Runtime* pRuntime,
149                          const wchar_t* propname,
150                          v8::Local<v8::Value> vp);
151   CJS_Return DelProperty(CJS_Runtime* pRuntime, const wchar_t* propname);
152   void Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv);
153 
154  private:
155   void UpdateGlobalPersistentVariables();
156   void CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime);
157   void DestroyGlobalPersisitentVariables();
158   CJS_Return SetGlobalVariables(const ByteString& propname,
159                                 JS_GlobalDataType nType,
160                                 double dData,
161                                 bool bData,
162                                 const ByteString& sData,
163                                 v8::Local<v8::Object> pData,
164                                 bool bDefaultPersistent);
165   void ObjectToArray(CJS_Runtime* pRuntime,
166                      v8::Local<v8::Object> pObj,
167                      CJS_GlobalVariableArray& array);
168   void PutObjectProperty(v8::Local<v8::Object> obj, CJS_KeyValue* pData);
169 
170   std::map<ByteString, std::unique_ptr<JSGlobalData>> m_MapGlobal;
171   WideString m_sFilePath;
172   CJS_GlobalData* m_pGlobalData;
173   CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
174 };
175 
176 }  // namespace
177 
178 const JSMethodSpec CJS_Global::MethodSpecs[] = {
179     {"setPersistent", setPersistent_static}};
180 
181 int CJS_Global::ObjDefnID = -1;
182 
183 // static
setPersistent_static(const v8::FunctionCallbackInfo<v8::Value> & info)184 void CJS_Global::setPersistent_static(
185     const v8::FunctionCallbackInfo<v8::Value>& info) {
186   JSMethod<JSGlobalAlternate, &JSGlobalAlternate::setPersistent>(
187       "setPersistent", "global", info);
188 }
189 
190 // static
queryprop_static(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Integer> & info)191 void CJS_Global::queryprop_static(
192     v8::Local<v8::String> property,
193     const v8::PropertyCallbackInfo<v8::Integer>& info) {
194   JSSpecialPropQuery<JSGlobalAlternate>("global", property, info);
195 }
196 
197 // static
getprop_static(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Value> & info)198 void CJS_Global::getprop_static(
199     v8::Local<v8::String> property,
200     const v8::PropertyCallbackInfo<v8::Value>& info) {
201   JSSpecialPropGet<JSGlobalAlternate>("global", property, info);
202 }
203 
204 // static
putprop_static(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value> & info)205 void CJS_Global::putprop_static(
206     v8::Local<v8::String> property,
207     v8::Local<v8::Value> value,
208     const v8::PropertyCallbackInfo<v8::Value>& info) {
209   JSSpecialPropPut<JSGlobalAlternate>("global", property, value, info);
210 }
211 
212 // static
delprop_static(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Boolean> & info)213 void CJS_Global::delprop_static(
214     v8::Local<v8::String> property,
215     const v8::PropertyCallbackInfo<v8::Boolean>& info) {
216   JSSpecialPropDel<JSGlobalAlternate>("global", property, info);
217 }
218 
219 // static
DefineAllProperties(CFXJS_Engine * pEngine)220 void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) {
221   pEngine->DefineObjAllProperties(
222       ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
223       CJS_Global::putprop_static, CJS_Global::delprop_static);
224 }
225 
226 // static
DefineJSObjects(CFXJS_Engine * pEngine)227 void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine) {
228   ObjDefnID = pEngine->DefineObj("global", FXJSOBJTYPE_STATIC,
229                                  JSConstructor<CJS_Global, JSGlobalAlternate>,
230                                  JSDestructor<CJS_Global>);
231   DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs));
232   DefineAllProperties(pEngine);
233 }
234 
InitInstance(IJS_Runtime * pIRuntime)235 void CJS_Global::InitInstance(IJS_Runtime* pIRuntime) {
236   CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
237   JSGlobalAlternate* pGlobal =
238       static_cast<JSGlobalAlternate*>(GetEmbedObject());
239   pGlobal->Initial(pRuntime->GetFormFillEnv());
240 }
241 
JSGlobalData()242 JSGlobalData::JSGlobalData()
243     : nType(JS_GlobalDataType::NUMBER),
244       dData(0),
245       bData(false),
246       sData(""),
247       bPersistent(false),
248       bDeleted(false) {}
249 
~JSGlobalData()250 JSGlobalData::~JSGlobalData() {
251   pData.Reset();
252 }
253 
JSGlobalAlternate(CJS_Object * pJSObject)254 JSGlobalAlternate::JSGlobalAlternate(CJS_Object* pJSObject)
255     : CJS_EmbedObj(pJSObject), m_pFormFillEnv(nullptr) {}
256 
~JSGlobalAlternate()257 JSGlobalAlternate::~JSGlobalAlternate() {
258   DestroyGlobalPersisitentVariables();
259   m_pGlobalData->Release();
260 }
261 
Initial(CPDFSDK_FormFillEnvironment * pFormFillEnv)262 void JSGlobalAlternate::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
263   m_pFormFillEnv.Reset(pFormFillEnv);
264   m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv);
265   UpdateGlobalPersistentVariables();
266 }
267 
QueryProperty(const wchar_t * propname)268 CJS_Return JSGlobalAlternate::QueryProperty(const wchar_t* propname) {
269   return CJS_Return(WideString(propname) != L"setPersistent");
270 }
271 
DelProperty(CJS_Runtime * pRuntime,const wchar_t * propname)272 CJS_Return JSGlobalAlternate::DelProperty(CJS_Runtime* pRuntime,
273                                           const wchar_t* propname) {
274   auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
275   if (it == m_MapGlobal.end())
276     return CJS_Return(false);
277 
278   it->second->bDeleted = true;
279   return CJS_Return(true);
280 }
281 
GetProperty(CJS_Runtime * pRuntime,const wchar_t * propname)282 CJS_Return JSGlobalAlternate::GetProperty(CJS_Runtime* pRuntime,
283                                           const wchar_t* propname) {
284   auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
285   if (it == m_MapGlobal.end())
286     return CJS_Return(true);
287 
288   JSGlobalData* pData = it->second.get();
289   if (pData->bDeleted)
290     return CJS_Return(true);
291 
292   switch (pData->nType) {
293     case JS_GlobalDataType::NUMBER:
294       return CJS_Return(pRuntime->NewNumber(pData->dData));
295     case JS_GlobalDataType::BOOLEAN:
296       return CJS_Return(pRuntime->NewBoolean(pData->bData));
297     case JS_GlobalDataType::STRING:
298       return CJS_Return(pRuntime->NewString(
299           WideString::FromLocal(pData->sData.c_str()).c_str()));
300     case JS_GlobalDataType::OBJECT:
301       return CJS_Return(
302           v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
303     case JS_GlobalDataType::NULLOBJ:
304       return CJS_Return(pRuntime->NewNull());
305     default:
306       break;
307   }
308   return CJS_Return(false);
309 }
310 
SetProperty(CJS_Runtime * pRuntime,const wchar_t * propname,v8::Local<v8::Value> vp)311 CJS_Return JSGlobalAlternate::SetProperty(CJS_Runtime* pRuntime,
312                                           const wchar_t* propname,
313                                           v8::Local<v8::Value> vp) {
314   ByteString sPropName = ByteString::FromUnicode(propname);
315   if (vp->IsNumber()) {
316     return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER,
317                               pRuntime->ToDouble(vp), false, "",
318                               v8::Local<v8::Object>(), false);
319   }
320   if (vp->IsBoolean()) {
321     return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0,
322                               pRuntime->ToBoolean(vp), "",
323                               v8::Local<v8::Object>(), false);
324   }
325   if (vp->IsString()) {
326     return SetGlobalVariables(
327         sPropName, JS_GlobalDataType::STRING, 0, false,
328         ByteString::FromUnicode(pRuntime->ToWideString(vp)),
329         v8::Local<v8::Object>(), false);
330   }
331   if (vp->IsObject()) {
332     return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0, false,
333                               "", pRuntime->ToObject(vp), false);
334   }
335   if (vp->IsNull()) {
336     return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0, false,
337                               "", v8::Local<v8::Object>(), false);
338   }
339   if (vp->IsUndefined()) {
340     DelProperty(pRuntime, propname);
341     return CJS_Return(true);
342   }
343   return CJS_Return(false);
344 }
345 
setPersistent(CJS_Runtime * pRuntime,const std::vector<v8::Local<v8::Value>> & params)346 CJS_Return JSGlobalAlternate::setPersistent(
347     CJS_Runtime* pRuntime,
348     const std::vector<v8::Local<v8::Value>>& params) {
349   if (params.size() != 2)
350     return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
351 
352   auto it = m_MapGlobal.find(
353       ByteString::FromUnicode(pRuntime->ToWideString(params[0])));
354   if (it == m_MapGlobal.end() || it->second->bDeleted)
355     return CJS_Return(JSGetStringFromID(JSMessage::kGlobalNotFoundError));
356 
357   it->second->bPersistent = pRuntime->ToBoolean(params[1]);
358   return CJS_Return(true);
359 }
360 
UpdateGlobalPersistentVariables()361 void JSGlobalAlternate::UpdateGlobalPersistentVariables() {
362   CJS_Runtime* pRuntime =
363       static_cast<CJS_Runtime*>(CFXJS_Engine::CurrentEngineFromIsolate(
364           m_pJSObject->ToV8Object()->GetIsolate()));
365 
366   for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
367     CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
368     switch (pData->data.nType) {
369       case JS_GlobalDataType::NUMBER:
370         SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER,
371                            pData->data.dData, false, "",
372                            v8::Local<v8::Object>(), pData->bPersistent == 1);
373         pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
374                                     pData->data.sKey.UTF8Decode(),
375                                     pRuntime->NewNumber(pData->data.dData));
376         break;
377       case JS_GlobalDataType::BOOLEAN:
378         SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0,
379                            pData->data.bData == 1, "", v8::Local<v8::Object>(),
380                            pData->bPersistent == 1);
381         pRuntime->PutObjectProperty(
382             m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
383             pRuntime->NewBoolean(pData->data.bData == 1));
384         break;
385       case JS_GlobalDataType::STRING:
386         SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0,
387                            false, pData->data.sData, v8::Local<v8::Object>(),
388                            pData->bPersistent == 1);
389         pRuntime->PutObjectProperty(
390             m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
391             pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringView()));
392         break;
393       case JS_GlobalDataType::OBJECT: {
394         v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(-1);
395         if (!pObj.IsEmpty()) {
396           PutObjectProperty(pObj, &pData->data);
397           SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0,
398                              false, "", pObj, pData->bPersistent == 1);
399           pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
400                                       pData->data.sKey.UTF8Decode(), pObj);
401         }
402       } break;
403       case JS_GlobalDataType::NULLOBJ:
404         SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0,
405                            false, "", v8::Local<v8::Object>(),
406                            pData->bPersistent == 1);
407         pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
408                                     pData->data.sKey.UTF8Decode(),
409                                     pRuntime->NewNull());
410         break;
411     }
412   }
413 }
414 
CommitGlobalPersisitentVariables(CJS_Runtime * pRuntime)415 void JSGlobalAlternate::CommitGlobalPersisitentVariables(
416     CJS_Runtime* pRuntime) {
417   for (const auto& iter : m_MapGlobal) {
418     ByteString name = iter.first;
419     JSGlobalData* pData = iter.second.get();
420     if (pData->bDeleted) {
421       m_pGlobalData->DeleteGlobalVariable(name);
422       continue;
423     }
424     switch (pData->nType) {
425       case JS_GlobalDataType::NUMBER:
426         m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
427         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
428         break;
429       case JS_GlobalDataType::BOOLEAN:
430         m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
431         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
432         break;
433       case JS_GlobalDataType::STRING:
434         m_pGlobalData->SetGlobalVariableString(name, pData->sData);
435         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
436         break;
437       case JS_GlobalDataType::OBJECT: {
438         CJS_GlobalVariableArray array;
439         v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(
440             GetJSObject()->GetIsolate(), pData->pData);
441         ObjectToArray(pRuntime, obj, array);
442         m_pGlobalData->SetGlobalVariableObject(name, array);
443         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
444       } break;
445       case JS_GlobalDataType::NULLOBJ:
446         m_pGlobalData->SetGlobalVariableNull(name);
447         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
448         break;
449     }
450   }
451 }
452 
ObjectToArray(CJS_Runtime * pRuntime,v8::Local<v8::Object> pObj,CJS_GlobalVariableArray & array)453 void JSGlobalAlternate::ObjectToArray(CJS_Runtime* pRuntime,
454                                       v8::Local<v8::Object> pObj,
455                                       CJS_GlobalVariableArray& array) {
456   std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
457   for (const auto& ws : pKeyList) {
458     ByteString sKey = ws.UTF8Encode();
459     v8::Local<v8::Value> v = pRuntime->GetObjectProperty(pObj, ws);
460     if (v->IsNumber()) {
461       CJS_KeyValue* pObjElement = new CJS_KeyValue;
462       pObjElement->nType = JS_GlobalDataType::NUMBER;
463       pObjElement->sKey = sKey;
464       pObjElement->dData = pRuntime->ToDouble(v);
465       array.Add(pObjElement);
466       continue;
467     }
468     if (v->IsBoolean()) {
469       CJS_KeyValue* pObjElement = new CJS_KeyValue;
470       pObjElement->nType = JS_GlobalDataType::BOOLEAN;
471       pObjElement->sKey = sKey;
472       pObjElement->dData = pRuntime->ToBoolean(v);
473       array.Add(pObjElement);
474       continue;
475     }
476     if (v->IsString()) {
477       ByteString sValue = ByteString::FromUnicode(pRuntime->ToWideString(v));
478       CJS_KeyValue* pObjElement = new CJS_KeyValue;
479       pObjElement->nType = JS_GlobalDataType::STRING;
480       pObjElement->sKey = sKey;
481       pObjElement->sData = sValue;
482       array.Add(pObjElement);
483       continue;
484     }
485     if (v->IsObject()) {
486       CJS_KeyValue* pObjElement = new CJS_KeyValue;
487       pObjElement->nType = JS_GlobalDataType::OBJECT;
488       pObjElement->sKey = sKey;
489       ObjectToArray(pRuntime, pRuntime->ToObject(v), pObjElement->objData);
490       array.Add(pObjElement);
491       continue;
492     }
493     if (v->IsNull()) {
494       CJS_KeyValue* pObjElement = new CJS_KeyValue;
495       pObjElement->nType = JS_GlobalDataType::NULLOBJ;
496       pObjElement->sKey = sKey;
497       array.Add(pObjElement);
498     }
499   }
500 }
501 
PutObjectProperty(v8::Local<v8::Object> pObj,CJS_KeyValue * pData)502 void JSGlobalAlternate::PutObjectProperty(v8::Local<v8::Object> pObj,
503                                           CJS_KeyValue* pData) {
504   CJS_Runtime* pRuntime = CJS_Runtime::CurrentRuntimeFromIsolate(
505       m_pJSObject->ToV8Object()->GetIsolate());
506 
507   for (int i = 0, sz = pData->objData.Count(); i < sz; i++) {
508     CJS_KeyValue* pObjData = pData->objData.GetAt(i);
509     switch (pObjData->nType) {
510       case JS_GlobalDataType::NUMBER:
511         pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
512                                     pRuntime->NewNumber(pObjData->dData));
513         break;
514       case JS_GlobalDataType::BOOLEAN:
515         pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
516                                     pRuntime->NewBoolean(pObjData->bData == 1));
517         break;
518       case JS_GlobalDataType::STRING:
519         pRuntime->PutObjectProperty(
520             pObj, pObjData->sKey.UTF8Decode(),
521             pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringView()));
522         break;
523       case JS_GlobalDataType::OBJECT: {
524         v8::Local<v8::Object> pNewObj = pRuntime->NewFxDynamicObj(-1);
525         if (!pNewObj.IsEmpty()) {
526           PutObjectProperty(pNewObj, pObjData);
527           pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
528                                       pNewObj);
529         }
530       } break;
531       case JS_GlobalDataType::NULLOBJ:
532         pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
533                                     pRuntime->NewNull());
534         break;
535     }
536   }
537 }
538 
DestroyGlobalPersisitentVariables()539 void JSGlobalAlternate::DestroyGlobalPersisitentVariables() {
540   m_MapGlobal.clear();
541 }
542 
SetGlobalVariables(const ByteString & propname,JS_GlobalDataType nType,double dData,bool bData,const ByteString & sData,v8::Local<v8::Object> pData,bool bDefaultPersistent)543 CJS_Return JSGlobalAlternate::SetGlobalVariables(const ByteString& propname,
544                                                  JS_GlobalDataType nType,
545                                                  double dData,
546                                                  bool bData,
547                                                  const ByteString& sData,
548                                                  v8::Local<v8::Object> pData,
549                                                  bool bDefaultPersistent) {
550   if (propname.IsEmpty())
551     return CJS_Return(false);
552 
553   auto it = m_MapGlobal.find(propname);
554   if (it != m_MapGlobal.end()) {
555     JSGlobalData* pTemp = it->second.get();
556     if (pTemp->bDeleted || pTemp->nType != nType) {
557       pTemp->dData = 0;
558       pTemp->bData = 0;
559       pTemp->sData.clear();
560       pTemp->nType = nType;
561     }
562     pTemp->bDeleted = false;
563     switch (nType) {
564       case JS_GlobalDataType::NUMBER:
565         pTemp->dData = dData;
566         break;
567       case JS_GlobalDataType::BOOLEAN:
568         pTemp->bData = bData;
569         break;
570       case JS_GlobalDataType::STRING:
571         pTemp->sData = sData;
572         break;
573       case JS_GlobalDataType::OBJECT:
574         pTemp->pData.Reset(pData->GetIsolate(), pData);
575         break;
576       case JS_GlobalDataType::NULLOBJ:
577         break;
578       default:
579         return CJS_Return(false);
580     }
581     return CJS_Return(true);
582   }
583 
584   auto pNewData = pdfium::MakeUnique<JSGlobalData>();
585   switch (nType) {
586     case JS_GlobalDataType::NUMBER:
587       pNewData->nType = JS_GlobalDataType::NUMBER;
588       pNewData->dData = dData;
589       pNewData->bPersistent = bDefaultPersistent;
590       break;
591     case JS_GlobalDataType::BOOLEAN:
592       pNewData->nType = JS_GlobalDataType::BOOLEAN;
593       pNewData->bData = bData;
594       pNewData->bPersistent = bDefaultPersistent;
595       break;
596     case JS_GlobalDataType::STRING:
597       pNewData->nType = JS_GlobalDataType::STRING;
598       pNewData->sData = sData;
599       pNewData->bPersistent = bDefaultPersistent;
600       break;
601     case JS_GlobalDataType::OBJECT:
602       pNewData->nType = JS_GlobalDataType::OBJECT;
603       pNewData->pData.Reset(pData->GetIsolate(), pData);
604       pNewData->bPersistent = bDefaultPersistent;
605       break;
606     case JS_GlobalDataType::NULLOBJ:
607       pNewData->nType = JS_GlobalDataType::NULLOBJ;
608       pNewData->bPersistent = bDefaultPersistent;
609       break;
610     default:
611       return CJS_Return(false);
612   }
613   m_MapGlobal[propname] = std::move(pNewData);
614   return CJS_Return(true);
615 }
616