Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cjs_global.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
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_object.h"
18#include "fxjs/fxv8.h"
19#include "fxjs/js_define.h"
20#include "fxjs/js_resources.h"
21#include "third_party/base/check.h"
22#include "third_party/base/containers/contains.h"
23#include "third_party/base/containers/span.h"
24#include "v8/include/v8-isolate.h"
25
26namespace {
27
28ByteString ByteStringFromV8Name(v8::Isolate* pIsolate,
29 v8::Local<v8::Name> name) {
30 CHECK(name->IsString());
31 return fxv8::ToByteString(pIsolate, name.As<v8::String>());
32}
33
34} // namespace
35
36CJS_Global::JSGlobalData::JSGlobalData() = default;
37
38CJS_Global::JSGlobalData::~JSGlobalData() = default;
39
40const JSMethodSpec CJS_Global::MethodSpecs[] = {
41 {"setPersistent", setPersistent_static}};
42
43uint32_t CJS_Global::ObjDefnID = 0;
44
45// static
46void CJS_Global::setPersistent_static(
47 const v8::FunctionCallbackInfo<v8::Value>& info) {
48 JSMethod<CJS_Global, &CJS_Global::setPersistent>("setPersistent", "global",
49 info);
50}
51
52// static
53void CJS_Global::queryprop_static(
54 v8::Local<v8::Name> property,
55 const v8::PropertyCallbackInfo<v8::Integer>& info) {
56 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
57 if (!pObj)
58 return;
59
60 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
61 if (pObj->HasProperty(bsProp))
62 info.GetReturnValue().Set(static_cast<int>(v8::PropertyAttribute::None));
63}
64
65// static
66void CJS_Global::getprop_static(
67 v8::Local<v8::Name> property,
68 const v8::PropertyCallbackInfo<v8::Value>& info) {
69 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
70 if (!pObj)
71 return;
72
73 CJS_Runtime* pRuntime = pObj->GetRuntime();
74 if (!pRuntime)
75 return;
76
77 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
78 CJS_Result result = pObj->GetProperty(pRuntime, bsProp);
79 if (result.HasError()) {
80 pRuntime->Error(
81 JSFormatErrorString("global", "GetProperty", result.Error()));
82 return;
83 }
84 if (result.HasReturn())
85 info.GetReturnValue().Set(result.Return());
86}
87
88// static
89void CJS_Global::putprop_static(
90 v8::Local<v8::Name> property,
91 v8::Local<v8::Value> value,
92 const v8::PropertyCallbackInfo<v8::Value>& info) {
93 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
94 if (!pObj)
95 return;
96
97 CJS_Runtime* pRuntime = pObj->GetRuntime();
98 if (!pRuntime)
99 return;
100
101 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
102 CJS_Result result = pObj->SetProperty(pRuntime, bsProp, value);
103 if (result.HasError()) {
104 pRuntime->Error(
105 JSFormatErrorString("global", "PutProperty", result.Error()));
106 return;
107 }
108 info.GetReturnValue().Set(value);
109}
110
111// static
112void CJS_Global::delprop_static(
113 v8::Local<v8::Name> property,
114 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
115 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
116 if (!pObj)
117 return;
118
119 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
120 if (pObj->DelProperty(bsProp))
121 info.GetReturnValue().Set(true);
122}
123
124void CJS_Global::enumprop_static(
125 const v8::PropertyCallbackInfo<v8::Array>& info) {
126 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
127 if (!pObj)
128 return;
129
130 CJS_Runtime* pRuntime = pObj->GetRuntime();
131 if (!pRuntime)
132 return;
133
134 pObj->EnumProperties(pRuntime, info);
135}
136
137// static
138void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) {
139 pEngine->DefineObjAllProperties(
140 ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
141 CJS_Global::putprop_static, CJS_Global::delprop_static,
142 CJS_Global::enumprop_static);
143}
144
145// static
146uint32_t CJS_Global::GetObjDefnID() {
147 return ObjDefnID;
148}
149
150// static
151void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine) {
152 ObjDefnID = pEngine->DefineObj("global", FXJSOBJTYPE_STATIC,
153 JSConstructor<CJS_Global>, JSDestructor);
154 DefineMethods(pEngine, ObjDefnID, MethodSpecs);
156}
157
158CJS_Global::CJS_Global(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
159 : CJS_Object(pObject, pRuntime),
161 UpdateGlobalPersistentVariables();
162}
163
164CJS_Global::~CJS_Global() {
165 DestroyGlobalPersisitentVariables();
166 m_pGlobalData.ExtractAsDangling()->Release();
167}
168
169bool CJS_Global::HasProperty(const ByteString& propname) {
170 return pdfium::Contains(m_MapGlobal, propname);
171}
172
173bool CJS_Global::DelProperty(const ByteString& propname) {
174 auto it = m_MapGlobal.find(propname);
175 if (it == m_MapGlobal.end())
176 return false;
177
178 it->second->bDeleted = true;
179 return true;
180}
181
182CJS_Result CJS_Global::GetProperty(CJS_Runtime* pRuntime,
183 const ByteString& propname) {
184 auto it = m_MapGlobal.find(propname);
185 if (it == m_MapGlobal.end())
187
188 JSGlobalData* pData = it->second.get();
189 if (pData->bDeleted)
191
192 switch (pData->nType) {
194 return CJS_Result::Success(pRuntime->NewNumber(pData->dData));
196 return CJS_Result::Success(pRuntime->NewBoolean(pData->bData));
199 pRuntime->NewString(pData->sData.AsStringView()));
200 case CFX_Value::DataType::kObject:
201 return CJS_Result::Success(
202 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
204 return CJS_Result::Success(pRuntime->NewNull());
205 }
206}
207
208CJS_Result CJS_Global::SetProperty(CJS_Runtime* pRuntime,
209 const ByteString& propname,
210 v8::Local<v8::Value> vp) {
211 if (vp->IsNumber()) {
212 return SetGlobalVariables(propname, CFX_Value::DataType::kNumber,
213 pRuntime->ToDouble(vp), false, ByteString(),
214 v8::Local<v8::Object>(), false);
215 }
216 if (vp->IsBoolean()) {
217 return SetGlobalVariables(propname, CFX_Value::DataType::kBoolean, 0,
218 pRuntime->ToBoolean(vp), ByteString(),
219 v8::Local<v8::Object>(), false);
220 }
221 if (vp->IsString()) {
222 return SetGlobalVariables(propname, CFX_Value::DataType::kString, 0, false,
223 pRuntime->ToByteString(vp),
224 v8::Local<v8::Object>(), false);
225 }
226 if (vp->IsObject()) {
227 return SetGlobalVariables(propname, CFX_Value::DataType::kObject, 0, false,
228 ByteString(), pRuntime->ToObject(vp), false);
229 }
230 if (vp->IsNull()) {
231 return SetGlobalVariables(propname, CFX_Value::DataType::kNull, 0, false,
232 ByteString(), v8::Local<v8::Object>(), false);
233 }
234 if (vp->IsUndefined()) {
235 DelProperty(propname);
237 }
239}
240
241void CJS_Global::EnumProperties(
242 CJS_Runtime* pRuntime,
243 const v8::PropertyCallbackInfo<v8::Array>& info) {
244 v8::Local<v8::Array> result = pRuntime->NewArray();
245 int idx = 0;
246 for (const auto& it : m_MapGlobal) {
247 if (it.second->bDeleted)
248 continue;
249 v8::Local<v8::Name> name = pRuntime->NewString(it.first.AsStringView());
250 pRuntime->PutArrayElement(result, idx, name);
251 ++idx;
252 }
253 info.GetReturnValue().Set(result);
254}
255
256CJS_Result CJS_Global::setPersistent(
257 CJS_Runtime* pRuntime,
258 pdfium::span<v8::Local<v8::Value>> params) {
259 if (params.size() != 2)
261
262 auto it = m_MapGlobal.find(pRuntime->ToByteString(params[0]));
263 if (it == m_MapGlobal.end() || it->second->bDeleted)
265
266 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
268}
269
270void CJS_Global::UpdateGlobalPersistentVariables() {
271 CJS_Runtime* pRuntime = GetRuntime();
272 if (!pRuntime)
273 return;
274
275 for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
276 CFX_GlobalData::Element* pData = m_pGlobalData->GetAt(i);
277 switch (pData->data.nType) {
278 case CFX_Value::DataType::kNumber:
279 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kNumber,
280 pData->data.dData, false, ByteString(),
281 v8::Local<v8::Object>(), pData->bPersistent);
282 pRuntime->PutObjectProperty(ToV8Object(),
283 pData->data.sKey.AsStringView(),
284 pRuntime->NewNumber(pData->data.dData));
285 break;
286 case CFX_Value::DataType::kBoolean:
287 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kBoolean, 0,
288 pData->data.bData == 1, ByteString(),
289 v8::Local<v8::Object>(), pData->bPersistent);
290 pRuntime->PutObjectProperty(
291 ToV8Object(), pData->data.sKey.AsStringView(),
292 pRuntime->NewBoolean(pData->data.bData == 1));
293 break;
294 case CFX_Value::DataType::kString:
295 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kString, 0,
296 false, pData->data.sData, v8::Local<v8::Object>(),
297 pData->bPersistent);
298 pRuntime->PutObjectProperty(
299 ToV8Object(), pData->data.sKey.AsStringView(),
300 pRuntime->NewString(pData->data.sData.AsStringView()));
301 break;
303 v8::Local<v8::Object> pObj = pRuntime->NewObject();
304 if (!pObj.IsEmpty()) {
305 PutObjectProperty(pObj, &pData->data);
306 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kObject, 0,
307 false, ByteString(), pObj, pData->bPersistent);
308 pRuntime->PutObjectProperty(ToV8Object(),
309 pData->data.sKey.AsStringView(), pObj);
310 }
311 } break;
312 case CFX_Value::DataType::kNull:
313 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kNull, 0,
314 false, ByteString(), v8::Local<v8::Object>(),
315 pData->bPersistent);
316 pRuntime->PutObjectProperty(
317 ToV8Object(), pData->data.sKey.AsStringView(), pRuntime->NewNull());
318 break;
319 }
320 }
321}
322
323void CJS_Global::CommitGlobalPersisitentVariables() {
324 CJS_Runtime* pRuntime = GetRuntime();
325 if (!pRuntime)
326 return;
327
328 for (const auto& iter : m_MapGlobal) {
329 ByteString name = iter.first;
330 JSGlobalData* pData = iter.second.get();
331 if (pData->bDeleted) {
332 m_pGlobalData->DeleteGlobalVariable(name);
333 continue;
334 }
335 switch (pData->nType) {
336 case CFX_Value::DataType::kNumber:
337 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
338 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
339 break;
340 case CFX_Value::DataType::kBoolean:
341 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
342 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
343 break;
344 case CFX_Value::DataType::kString:
345 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
346 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
347 break;
348 case CFX_Value::DataType::kObject: {
349 v8::Local<v8::Object> obj =
350 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData);
351 m_pGlobalData->SetGlobalVariableObject(name,
352 ObjectToArray(pRuntime, obj));
353 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
354 } break;
355 case CFX_Value::DataType::kNull:
356 m_pGlobalData->SetGlobalVariableNull(name);
357 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
358 break;
359 }
360 }
361}
362
363std::vector<std::unique_ptr<CFX_KeyValue>> CJS_Global::ObjectToArray(
364 CJS_Runtime* pRuntime,
365 v8::Local<v8::Object> pObj) {
366 std::vector<std::unique_ptr<CFX_KeyValue>> array;
367 std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
368 for (const auto& ws : pKeyList) {
369 ByteString sKey = ws.ToUTF8();
370 v8::Local<v8::Value> v =
371 pRuntime->GetObjectProperty(pObj, sKey.AsStringView());
372 if (v->IsNumber()) {
373 auto pObjElement = std::make_unique<CFX_KeyValue>();
374 pObjElement->nType = CFX_Value::DataType::kNumber;
375 pObjElement->sKey = sKey;
376 pObjElement->dData = pRuntime->ToDouble(v);
377 array.push_back(std::move(pObjElement));
378 continue;
379 }
380 if (v->IsBoolean()) {
381 auto pObjElement = std::make_unique<CFX_KeyValue>();
382 pObjElement->nType = CFX_Value::DataType::kBoolean;
383 pObjElement->sKey = sKey;
384 pObjElement->dData = pRuntime->ToBoolean(v);
385 array.push_back(std::move(pObjElement));
386 continue;
387 }
388 if (v->IsString()) {
389 ByteString sValue = pRuntime->ToByteString(v);
390 auto pObjElement = std::make_unique<CFX_KeyValue>();
391 pObjElement->nType = CFX_Value::DataType::kString;
392 pObjElement->sKey = sKey;
393 pObjElement->sData = sValue;
394 array.push_back(std::move(pObjElement));
395 continue;
396 }
397 if (v->IsObject()) {
398 auto pObjElement = std::make_unique<CFX_KeyValue>();
399 pObjElement->nType = CFX_Value::DataType::kObject;
400 pObjElement->sKey = sKey;
401 pObjElement->objData = ObjectToArray(pRuntime, pRuntime->ToObject(v));
402 array.push_back(std::move(pObjElement));
403 continue;
404 }
405 if (v->IsNull()) {
406 auto pObjElement = std::make_unique<CFX_KeyValue>();
407 pObjElement->nType = CFX_Value::DataType::kNull;
408 pObjElement->sKey = sKey;
409 array.push_back(std::move(pObjElement));
410 }
411 }
412 return array;
413}
414
415void CJS_Global::PutObjectProperty(v8::Local<v8::Object> pObj,
416 CFX_KeyValue* pData) {
417 CJS_Runtime* pRuntime = GetRuntime();
418 if (pRuntime)
419 return;
420
421 for (size_t i = 0; i < pData->objData.size(); ++i) {
422 CFX_KeyValue* pObjData = pData->objData.at(i).get();
423 switch (pObjData->nType) {
424 case CFX_Value::DataType::kNumber:
425 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
426 pRuntime->NewNumber(pObjData->dData));
427 break;
428 case CFX_Value::DataType::kBoolean:
429 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
430 pRuntime->NewBoolean(pObjData->bData == 1));
431 break;
432 case CFX_Value::DataType::kString:
433 pRuntime->PutObjectProperty(
434 pObj, pObjData->sKey.AsStringView(),
435 pRuntime->NewString(pObjData->sData.AsStringView()));
436 break;
437 case CFX_Value::DataType::kObject: {
438 v8::Local<v8::Object> pNewObj = pRuntime->NewObject();
439 if (!pNewObj.IsEmpty()) {
440 PutObjectProperty(pNewObj, pObjData);
441 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
442 pNewObj);
443 }
444 } break;
445 case CFX_Value::DataType::kNull:
446 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
447 pRuntime->NewNull());
448 break;
449 }
450 }
451}
452
453void CJS_Global::DestroyGlobalPersisitentVariables() {
454 m_MapGlobal.clear();
455}
456
457CJS_Result CJS_Global::SetGlobalVariables(const ByteString& propname,
458 CFX_Value::DataType nType,
459 double dData,
460 bool bData,
461 const ByteString& sData,
462 v8::Local<v8::Object> pData,
463 bool bDefaultPersistent) {
464 if (propname.IsEmpty())
466
467 auto it = m_MapGlobal.find(propname);
468 if (it != m_MapGlobal.end()) {
469 JSGlobalData* pTemp = it->second.get();
470 if (pTemp->bDeleted || pTemp->nType != nType) {
471 pTemp->dData = 0;
472 pTemp->bData = false;
473 pTemp->sData.clear();
474 pTemp->nType = nType;
475 }
476 pTemp->bDeleted = false;
477 switch (nType) {
479 pTemp->dData = dData;
480 break;
482 pTemp->bData = bData;
483 break;
485 pTemp->sData = sData;
486 break;
488 pTemp->pData.Reset(pData->GetIsolate(), pData);
489 break;
491 break;
492 }
494 }
495
496 auto pNewData = std::make_unique<JSGlobalData>();
497 switch (nType) {
499 pNewData->nType = CFX_Value::DataType::kNumber;
500 pNewData->dData = dData;
501 pNewData->bPersistent = bDefaultPersistent;
502 break;
504 pNewData->nType = CFX_Value::DataType::kBoolean;
505 pNewData->bData = bData;
506 pNewData->bPersistent = bDefaultPersistent;
507 break;
509 pNewData->nType = CFX_Value::DataType::kString;
510 pNewData->sData = sData;
511 pNewData->bPersistent = bDefaultPersistent;
512 break;
514 pNewData->nType = CFX_Value::DataType::kObject;
515 pNewData->pData.Reset(pData->GetIsolate(), pData);
516 pNewData->bPersistent = bDefaultPersistent;
517 break;
519 pNewData->nType = CFX_Value::DataType::kNull;
520 pNewData->bPersistent = bDefaultPersistent;
521 break;
522 }
523 m_MapGlobal[propname] = std::move(pNewData);
525}
@ FXJSOBJTYPE_STATIC
double dData
DataType nType
CJS_Global(v8::Local< v8::Object > pObject, CJS_Runtime *pRuntime)
static void DefineAllProperties(CFXJS_Engine *pEngine)
~CJS_Global() override
static uint32_t GetObjDefnID()
static void DefineJSObjects(CFXJS_Engine *pEngine)
CJS_Runtime * GetRuntime() const
Definition cjs_object.h:54
static void DefineMethods(CFXJS_Engine *pEngine, uint32_t nObjDefnID, pdfium::span< const JSMethodSpec > consts)
static CJS_Result Success()
Definition cjs_result.h:27
static CJS_Result Failure(JSMessage id)
Definition cjs_result.h:34
bool IsEmpty() const
Definition bytestring.h:119
JSMessage
@ kObjectTypeError
@ kGlobalNotFoundError
@ kUnknownProperty
#define CHECK(cvref)