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