7#include "fxjs/cjs_global.h"
13#include "core/fxcrt/check.h"
14#include "core/fxcrt/containers/contains.h"
15#include "core/fxcrt/fx_extension.h"
16#include "core/fxcrt/span.h"
17#include "fxjs/cfx_globaldata.h"
18#include "fxjs/cfx_keyvalue.h"
19#include "fxjs/cjs_event_context.h"
20#include "fxjs/cjs_object.h"
22#include "fxjs/js_define.h"
23#include "fxjs/js_resources.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",
53v8::Intercepted 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());
58 return v8::Intercepted::kNo;
61 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
62 if (!pObj->HasProperty(bsProp)) {
63 return v8::Intercepted::kNo;
66 info.GetReturnValue().Set(
static_cast<
int>(v8::PropertyAttribute::None));
67 return v8::Intercepted::kYes;
71v8::Intercepted CJS_Global::getprop_static(
72 v8::Local<v8::Name> property,
73 const v8::PropertyCallbackInfo<v8::Value>& info) {
74 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
76 return v8::Intercepted::kNo;
79 CJS_Runtime* pRuntime = pObj->GetRuntime();
81 return v8::Intercepted::kNo;
84 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
85 CJS_Result result = pObj->GetProperty(pRuntime, bsProp);
86 if (result.HasError()) {
88 JSFormatErrorString(
"global",
"GetProperty", result.Error()));
89 return v8::Intercepted::kYes;
91 if (!result.HasReturn()) {
92 return v8::Intercepted::kNo;
95 info.GetReturnValue().Set(result.Return());
96 return v8::Intercepted::kYes;
100v8::Intercepted CJS_Global::putprop_static(
101 v8::Local<v8::Name> property,
102 v8::Local<v8::Value> value,
103 const v8::PropertyCallbackInfo<
void>& info) {
104 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
106 return v8::Intercepted::kNo;
109 CJS_Runtime* pRuntime = pObj->GetRuntime();
111 return v8::Intercepted::kNo;
114 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
115 CJS_Result result = pObj->SetProperty(pRuntime, bsProp, value);
116 if (result.HasError()) {
118 JSFormatErrorString(
"global",
"PutProperty", result.Error()));
119 return v8::Intercepted::kYes;
121 return v8::Intercepted::kYes;
125v8::Intercepted CJS_Global::delprop_static(
126 v8::Local<v8::Name> property,
127 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
128 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
130 return v8::Intercepted::kNo;
133 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
134 if (!pObj->DelProperty(bsProp)) {
135 return v8::Intercepted::kNo;
138 info.GetReturnValue().Set(
true);
139 return v8::Intercepted::kYes;
142void CJS_Global::enumprop_static(
143 const v8::PropertyCallbackInfo<v8::Array>& info) {
144 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
148 CJS_Runtime* pRuntime = pObj->GetRuntime();
152 pObj->EnumProperties(pRuntime, info);
157 pEngine->DefineObjAllProperties(
158 ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
159 CJS_Global::putprop_static, CJS_Global::delprop_static,
160 CJS_Global::enumprop_static);
171 JSConstructor<CJS_Global>, JSDestructor);
172 DefineMethods(pEngine, ObjDefnID, MethodSpecs);
176CJS_Global::
CJS_Global(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
179 UpdateGlobalPersistentVariables();
183 DestroyGlobalPersisitentVariables();
184 m_pGlobalData.ExtractAsDangling()->Release();
187bool CJS_Global::HasProperty(
const ByteString& propname) {
188 return pdfium::Contains(m_MapGlobal, propname);
191bool CJS_Global::DelProperty(
const ByteString& propname) {
192 auto it = m_MapGlobal.find(propname);
193 if (it == m_MapGlobal.end())
196 it->second->bDeleted =
true;
200CJS_Result CJS_Global::GetProperty(CJS_Runtime* pRuntime,
202 auto it = m_MapGlobal.find(propname);
203 if (it == m_MapGlobal.end())
206 JSGlobalData* pData = it->second.get();
217 pRuntime->NewString(pData->sData.AsStringView())
);
218 case CFX_Value::DataType::kObject:
219 return CJS_Result::Success(
220 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
226CJS_Result CJS_Global::SetProperty(CJS_Runtime* pRuntime,
228 v8::Local<v8::Value> vp) {
229 if (vp->IsNumber()) {
230 return SetGlobalVariables(propname, CFX_Value::DataType::kNumber,
231 pRuntime->ToDouble(vp),
false, ByteString(),
232 v8::Local<v8::Object>(),
false);
234 if (vp->IsBoolean()) {
235 return SetGlobalVariables(propname, CFX_Value::DataType::kBoolean, 0,
236 pRuntime->ToBoolean(vp), ByteString(),
237 v8::Local<v8::Object>(),
false);
239 if (vp->IsString()) {
240 return SetGlobalVariables(propname, CFX_Value::DataType::kString, 0,
false,
241 pRuntime->ToByteString(vp),
242 v8::Local<v8::Object>(),
false);
244 if (vp->IsObject()) {
245 return SetGlobalVariables(propname, CFX_Value::DataType::kObject, 0,
false,
246 ByteString(), pRuntime->ToObject(vp),
false);
249 return SetGlobalVariables(propname, CFX_Value::DataType::kNull, 0,
false,
250 ByteString(), v8::Local<v8::Object>(),
false);
252 if (vp->IsUndefined()) {
253 DelProperty(propname);
259void CJS_Global::EnumProperties(
260 CJS_Runtime* pRuntime,
261 const v8::PropertyCallbackInfo<v8::Array>& info) {
262 v8::Local<v8::Array> result = pRuntime->NewArray();
264 for (
const auto& it : m_MapGlobal) {
265 if (it.second->bDeleted)
267 v8::Local<v8::Name> name = pRuntime->NewString(it.first.AsStringView());
268 pRuntime->PutArrayElement(result, idx, name);
271 info.GetReturnValue().Set(result);
275 CJS_Runtime* pRuntime,
276 pdfium::span<v8::Local<v8::Value>> params) {
277 if (params.size() != 2)
280 auto it = m_MapGlobal.find(pRuntime->ToByteString(params[0]));
281 if (it == m_MapGlobal.end() || it->second->bDeleted)
284 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
288void CJS_Global::UpdateGlobalPersistentVariables() {
293 for (
int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
295 switch (pData->data.nType) {
296 case CFX_Value::DataType::kNumber:
297 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kNumber,
298 pData->data.dData,
false, ByteString(),
299 v8::Local<v8::Object>(), pData->bPersistent);
300 pRuntime->PutObjectProperty(ToV8Object(),
301 pData->data.sKey.AsStringView(),
302 pRuntime->NewNumber(pData->data.dData));
304 case CFX_Value::DataType::kBoolean:
305 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kBoolean, 0,
306 pData->data.bData == 1, ByteString(),
307 v8::Local<v8::Object>(), pData->bPersistent);
308 pRuntime->PutObjectProperty(
309 ToV8Object(), pData->data.sKey.AsStringView(),
310 pRuntime->NewBoolean(pData->data.bData == 1));
312 case CFX_Value::DataType::kString:
313 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kString, 0,
314 false, pData->data.sData, v8::Local<v8::Object>(),
316 pRuntime->PutObjectProperty(
317 ToV8Object(), pData->data.sKey.AsStringView(),
318 pRuntime->NewString(pData->data.sData.AsStringView()));
321 v8::Local<v8::Object> pObj = pRuntime->NewObject();
322 if (!pObj.IsEmpty()) {
323 PutObjectProperty(pObj, &pData->data);
324 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kObject, 0,
325 false, ByteString(), pObj, pData->bPersistent);
326 pRuntime->PutObjectProperty(ToV8Object(),
327 pData->data.sKey.AsStringView(), pObj);
330 case CFX_Value::DataType::kNull:
331 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kNull, 0,
332 false, ByteString(), v8::Local<v8::Object>(),
334 pRuntime->PutObjectProperty(
335 ToV8Object(), pData->data.sKey.AsStringView(), pRuntime->NewNull());
341void CJS_Global::CommitGlobalPersisitentVariables() {
346 for (
const auto& iter : m_MapGlobal) {
347 ByteString name = iter.first;
348 JSGlobalData* pData = iter.second.get();
349 if (pData->bDeleted) {
350 m_pGlobalData->DeleteGlobalVariable(name);
353 switch (pData->nType) {
354 case CFX_Value::DataType::kNumber:
355 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
356 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
358 case CFX_Value::DataType::kBoolean:
359 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
360 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
362 case CFX_Value::DataType::kString:
363 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
364 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
366 case CFX_Value::DataType::kObject: {
367 v8::Local<v8::Object> obj =
368 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData);
369 m_pGlobalData->SetGlobalVariableObject(name,
370 ObjectToArray(pRuntime, obj));
371 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
373 case CFX_Value::DataType::kNull:
374 m_pGlobalData->SetGlobalVariableNull(name);
375 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
381std::vector<std::unique_ptr<CFX_KeyValue>> CJS_Global::ObjectToArray(
382 CJS_Runtime* pRuntime,
383 v8::Local<v8::Object> pObj) {
384 std::vector<std::unique_ptr<CFX_KeyValue>> array;
385 std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
386 for (
const auto& ws : pKeyList) {
387 ByteString sKey = ws.ToUTF8();
388 v8::Local<v8::Value> v =
389 pRuntime->GetObjectProperty(pObj, sKey.AsStringView());
391 auto pObjElement = std::make_unique<CFX_KeyValue>();
392 pObjElement->nType = CFX_Value::DataType::kNumber;
393 pObjElement->sKey = sKey;
394 pObjElement->dData = pRuntime->ToDouble(v);
395 array.push_back(std::move(pObjElement));
398 if (v->IsBoolean()) {
399 auto pObjElement = std::make_unique<CFX_KeyValue>();
400 pObjElement->nType = CFX_Value::DataType::kBoolean;
401 pObjElement->sKey = sKey;
402 pObjElement->dData = pRuntime->ToBoolean(v);
403 array.push_back(std::move(pObjElement));
407 ByteString sValue = pRuntime->ToByteString(v);
408 auto pObjElement = std::make_unique<CFX_KeyValue>();
409 pObjElement->nType = CFX_Value::DataType::kString;
410 pObjElement->sKey = sKey;
411 pObjElement->sData = sValue;
412 array.push_back(std::move(pObjElement));
416 auto pObjElement = std::make_unique<CFX_KeyValue>();
417 pObjElement->nType = CFX_Value::DataType::kObject;
418 pObjElement->sKey = sKey;
419 pObjElement->objData = ObjectToArray(pRuntime, pRuntime->ToObject(v));
420 array.push_back(std::move(pObjElement));
424 auto pObjElement = std::make_unique<CFX_KeyValue>();
425 pObjElement->nType = CFX_Value::DataType::kNull;
426 pObjElement->sKey = sKey;
427 array.push_back(std::move(pObjElement));
433void CJS_Global::PutObjectProperty(v8::Local<v8::Object> pObj,
434 CFX_KeyValue* pData) {
435 CJS_Runtime* pRuntime = GetRuntime();
439 for (size_t i = 0; i < pData->objData.size(); ++i) {
440 CFX_KeyValue* pObjData = pData->objData.at(i).get();
441 switch (pObjData->nType) {
442 case CFX_Value::DataType::kNumber:
443 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
444 pRuntime->NewNumber(pObjData->dData));
446 case CFX_Value::DataType::kBoolean:
447 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
448 pRuntime->NewBoolean(pObjData->bData == 1));
450 case CFX_Value::DataType::kString:
451 pRuntime->PutObjectProperty(
452 pObj, pObjData->sKey.AsStringView(),
453 pRuntime->NewString(pObjData->sData.AsStringView()));
455 case CFX_Value::DataType::kObject: {
456 v8::Local<v8::Object> pNewObj = pRuntime->NewObject();
457 if (!pNewObj.IsEmpty()) {
458 PutObjectProperty(pNewObj, pObjData);
459 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
463 case CFX_Value::DataType::kNull:
464 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
465 pRuntime->NewNull());
471void CJS_Global::DestroyGlobalPersisitentVariables() {
480 v8::Local<v8::Object> pData,
481 bool bDefaultPersistent) {
482 if (propname.IsEmpty())
485 auto it = m_MapGlobal.find(propname);
486 if (it != m_MapGlobal.end()) {
487 JSGlobalData* pTemp = it->second.get();
488 if (pTemp->bDeleted || pTemp
->nType != nType) {
491 pTemp->sData.clear();
494 pTemp->bDeleted =
false;
503 pTemp->sData = sData;
506 pTemp->pData.Reset(pData->GetIsolate(), pData);
514 auto pNewData =
std::make_unique<JSGlobalData>();
518 pNewData->dData = dData;
519 pNewData->bPersistent = bDefaultPersistent;
523 pNewData->bData = bData;
524 pNewData->bPersistent = bDefaultPersistent;
528 pNewData->sData = sData;
529 pNewData->bPersistent = bDefaultPersistent;
533 pNewData->pData.Reset(pData->GetIsolate(), pData);
534 pNewData->bPersistent = bDefaultPersistent;
538 pNewData->bPersistent = bDefaultPersistent;
541 m_MapGlobal[propname] = std::move(pNewData);
fxcrt::ByteString ByteString
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 CJS_Result Success()
static CJS_Result Failure(JSMessage id)