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