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