7#include "fxjs/cjs_global.h"
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"
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"
28ByteString ByteStringFromV8Name(v8::Isolate* pIsolate,
29 v8::Local<v8::Name> name) {
30 CHECK(name->IsString());
31 return fxv8::ToByteString(pIsolate, name.As<v8::String>());
36CJS_Global::JSGlobalData::JSGlobalData() =
default;
38CJS_Global::JSGlobalData::~JSGlobalData() =
default;
41 {
"setPersistent", setPersistent_static}};
43uint32_t CJS_Global::ObjDefnID = 0;
46void CJS_Global::setPersistent_static(
47 const v8::FunctionCallbackInfo<v8::Value>& info) {
48 JSMethod<CJS_Global, &CJS_Global::setPersistent>(
"setPersistent",
"global",
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());
60 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
61 if (pObj->HasProperty(bsProp))
62 info.GetReturnValue().Set(
static_cast<
int>(v8::PropertyAttribute::None));
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());
73 CJS_Runtime* pRuntime = pObj->GetRuntime();
77 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
78 CJS_Result result = pObj->GetProperty(pRuntime, bsProp);
79 if (result.HasError()) {
81 JSFormatErrorString(
"global",
"GetProperty", result.Error()));
84 if (result.HasReturn())
85 info.GetReturnValue().Set(result.Return());
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());
97 CJS_Runtime* pRuntime = pObj->GetRuntime();
101 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
102 CJS_Result result = pObj->SetProperty(pRuntime, bsProp, value);
103 if (result.HasError()) {
105 JSFormatErrorString(
"global",
"PutProperty", result.Error()));
108 info.GetReturnValue().Set(value);
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());
119 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
120 if (pObj->DelProperty(bsProp))
121 info.GetReturnValue().Set(
true);
124void CJS_Global::enumprop_static(
125 const v8::PropertyCallbackInfo<v8::Array>& info) {
126 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
130 CJS_Runtime* pRuntime = pObj->GetRuntime();
134 pObj->EnumProperties(pRuntime, info);
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);
153 JSConstructor<CJS_Global>, JSDestructor);
158CJS_Global::
CJS_Global(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
161 UpdateGlobalPersistentVariables();
165 DestroyGlobalPersisitentVariables();
166 m_pGlobalData.ExtractAsDangling()->Release();
169bool CJS_Global::HasProperty(
const ByteString& propname) {
170 return pdfium::Contains(m_MapGlobal, propname);
173bool CJS_Global::DelProperty(
const ByteString& propname) {
174 auto it = m_MapGlobal.find(propname);
175 if (it == m_MapGlobal.end())
178 it->second->bDeleted =
true;
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())
188 JSGlobalData* pData = it->second.get();
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));
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);
216 if (vp->IsBoolean()) {
217 return SetGlobalVariables(propname, CFX_Value::DataType::kBoolean, 0,
218 pRuntime->ToBoolean(vp), ByteString(),
219 v8::Local<v8::Object>(),
false);
221 if (vp->IsString()) {
222 return SetGlobalVariables(propname, CFX_Value::DataType::kString, 0,
false,
223 pRuntime->ToByteString(vp),
224 v8::Local<v8::Object>(),
false);
226 if (vp->IsObject()) {
227 return SetGlobalVariables(propname, CFX_Value::DataType::kObject, 0,
false,
228 ByteString(), pRuntime->ToObject(vp),
false);
231 return SetGlobalVariables(propname, CFX_Value::DataType::kNull, 0,
false,
232 ByteString(), v8::Local<v8::Object>(),
false);
234 if (vp->IsUndefined()) {
235 DelProperty(propname);
241void CJS_Global::EnumProperties(
242 CJS_Runtime* pRuntime,
243 const v8::PropertyCallbackInfo<v8::Array>& info) {
244 v8::Local<v8::Array> result = pRuntime->NewArray();
246 for (
const auto& it : m_MapGlobal) {
247 if (it.second->bDeleted)
249 v8::Local<v8::Name> name = pRuntime->NewString(it.first.AsStringView());
250 pRuntime->PutArrayElement(result, idx, name);
253 info.GetReturnValue().Set(result);
257 CJS_Runtime* pRuntime,
258 pdfium::span<v8::Local<v8::Value>> params) {
259 if (params.size() != 2)
262 auto it = m_MapGlobal.find(pRuntime->ToByteString(params[0]));
263 if (it == m_MapGlobal.end() || it->second->bDeleted)
266 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
270void CJS_Global::UpdateGlobalPersistentVariables() {
275 for (
int i = 0, sz = m_pGlobalData->GetSize(); i < sz; 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));
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));
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>(),
298 pRuntime->PutObjectProperty(
299 ToV8Object(), pData->data.sKey.AsStringView(),
300 pRuntime->NewString(pData->data.sData.AsStringView()));
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);
312 case CFX_Value::DataType::kNull:
313 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kNull, 0,
314 false, ByteString(), v8::Local<v8::Object>(),
316 pRuntime->PutObjectProperty(
317 ToV8Object(), pData->data.sKey.AsStringView(), pRuntime->NewNull());
323void CJS_Global::CommitGlobalPersisitentVariables() {
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);
335 switch (pData->nType) {
336 case CFX_Value::DataType::kNumber:
337 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
338 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
340 case CFX_Value::DataType::kBoolean:
341 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
342 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
344 case CFX_Value::DataType::kString:
345 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
346 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
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);
355 case CFX_Value::DataType::kNull:
356 m_pGlobalData->SetGlobalVariableNull(name);
357 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
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());
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));
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));
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));
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));
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));
415void CJS_Global::PutObjectProperty(v8::Local<v8::Object> pObj,
416 CFX_KeyValue* pData) {
417 CJS_Runtime* pRuntime = GetRuntime();
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));
428 case CFX_Value::DataType::kBoolean:
429 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
430 pRuntime->NewBoolean(pObjData->bData == 1));
432 case CFX_Value::DataType::kString:
433 pRuntime->PutObjectProperty(
434 pObj, pObjData->sKey.AsStringView(),
435 pRuntime->NewString(pObjData->sData.AsStringView()));
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(),
445 case CFX_Value::DataType::kNull:
446 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
447 pRuntime->NewNull());
453void CJS_Global::DestroyGlobalPersisitentVariables() {
457CJS_Result CJS_Global::SetGlobalVariables(
const ByteString& propname,
461 const ByteString& sData,
462 v8::Local<v8::Object> pData,
463 bool bDefaultPersistent) {
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) {
473 pTemp->sData.clear();
476 pTemp->bDeleted =
false;
485 pTemp->sData = sData;
488 pTemp->pData.Reset(pData->GetIsolate(), pData);
496 auto pNewData =
std::make_unique<JSGlobalData>();
500 pNewData->dData = dData;
501 pNewData->bPersistent = bDefaultPersistent;
505 pNewData->bData = bData;
506 pNewData->bPersistent = bDefaultPersistent;
510 pNewData->sData = sData;
511 pNewData->bPersistent = bDefaultPersistent;
515 pNewData->pData.Reset(pData->GetIsolate(), pData);
516 pNewData->bPersistent = bDefaultPersistent;
520 pNewData->bPersistent = bDefaultPersistent;
523 m_MapGlobal[propname] = std::move(pNewData);
CJS_Global(v8::Local< v8::Object > pObject, CJS_Runtime *pRuntime)
static void DefineAllProperties(CFXJS_Engine *pEngine)
static uint32_t GetObjDefnID()
static void DefineJSObjects(CFXJS_Engine *pEngine)
CJS_Runtime * GetRuntime() const
static void DefineMethods(CFXJS_Engine *pEngine, uint32_t nObjDefnID, pdfium::span< const JSMethodSpec > consts)
static CJS_Result Success()
static CJS_Result Failure(JSMessage id)