blob: 5582682f5af078872e34cf9d867c945d87298f31 [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2014 The PDFium Authors
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclaire0345a42017-10-30 20:20:42 +00007#include "fxjs/cjs_global.h"
Tom Sepez37458412015-10-06 11:33:46 -07008
Dan Sinclair4b172c42017-10-23 11:22:31 -04009#include <memory>
Tom Sepeza7757232017-04-18 11:10:39 -070010#include <utility>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050011#include <vector>
12
Dan Sinclaircfb19442017-04-20 13:13:04 -040013#include "core/fxcrt/fx_extension.h"
Tom Sepez41d04e12018-10-30 22:07:36 +000014#include "fxjs/cfx_globaldata.h"
15#include "fxjs/cfx_keyvalue.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000016#include "fxjs/cjs_event_context.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000017#include "fxjs/cjs_object.h"
Tom Sepez494efc72020-11-30 20:50:59 +000018#include "fxjs/fxv8.h"
Tom Sepez221f0b32018-06-04 22:11:27 +000019#include "fxjs/js_define.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000020#include "fxjs/js_resources.h"
Tom Sepez494efc72020-11-30 20:50:59 +000021#include "third_party/base/check.h"
Tom Sepez975aae52022-05-13 23:53:08 +000022#include "third_party/base/containers/contains.h"
Dan Elphick05673a32021-09-09 15:42:55 +000023#include "v8/include/v8-isolate.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070024
Dan Sinclair4b172c42017-10-23 11:22:31 -040025namespace {
26
Tom Sepez3f417872022-05-16 16:58:14 +000027ByteString ByteStringFromV8Name(v8::Isolate* pIsolate,
28 v8::Local<v8::Name> name) {
Tom Sepez10b10c42022-05-18 20:35:29 +000029 CHECK(name->IsString());
30 return fxv8::ToByteString(pIsolate, name.As<v8::String>());
Lei Zhang5b346562018-08-28 23:36:08 +000031}
32
Dan Sinclair4b172c42017-10-23 11:22:31 -040033} // namespace
34
Tom Sepez4a463d52018-11-07 22:32:41 +000035CJS_Global::JSGlobalData::JSGlobalData() = default;
Dan Sinclairf7435522018-02-05 22:27:22 +000036
Tom Sepez4a463d52018-11-07 22:32:41 +000037CJS_Global::JSGlobalData::~JSGlobalData() = default;
Dan Sinclairf7435522018-02-05 22:27:22 +000038
Dan Sinclairc94a7932017-10-26 16:48:57 -040039const JSMethodSpec CJS_Global::MethodSpecs[] = {
Dan Sinclair909fa2d2017-12-12 01:53:28 +000040 {"setPersistent", setPersistent_static}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070041
Tom Sepezb4958712020-10-13 20:30:43 +000042uint32_t CJS_Global::ObjDefnID = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070043
Dan Sinclair4b172c42017-10-23 11:22:31 -040044// static
45void CJS_Global::setPersistent_static(
46 const v8::FunctionCallbackInfo<v8::Value>& info) {
Dan Sinclairf7435522018-02-05 22:27:22 +000047 JSMethod<CJS_Global, &CJS_Global::setPersistent>("setPersistent", "global",
48 info);
Dan Sinclair4b172c42017-10-23 11:22:31 -040049}
50
Dan Sinclairef299532017-10-26 16:48:30 -040051// static
Dan Sinclair89d26c82017-10-26 12:21:28 -040052void CJS_Global::queryprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +000053 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -040054 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Tom Sepez3f417872022-05-16 16:58:14 +000055 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
56 if (!pObj)
57 return;
58
59 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
60 if (pObj->HasProperty(bsProp))
61 info.GetReturnValue().Set(static_cast<int>(v8::PropertyAttribute::None));
Dan Sinclair89d26c82017-10-26 12:21:28 -040062}
63
Dan Sinclairef299532017-10-26 16:48:30 -040064// static
Dan Sinclair89d26c82017-10-26 12:21:28 -040065void CJS_Global::getprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +000066 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -040067 const v8::PropertyCallbackInfo<v8::Value>& info) {
Tom Sepez3f417872022-05-16 16:58:14 +000068 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
69 if (!pObj)
70 return;
71
72 CJS_Runtime* pRuntime = pObj->GetRuntime();
73 if (!pRuntime)
74 return;
75
76 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
77 CJS_Result result = pObj->GetProperty(pRuntime, bsProp);
78 if (result.HasError()) {
79 pRuntime->Error(
80 JSFormatErrorString("global", "GetProperty", result.Error()));
81 return;
82 }
83 if (result.HasReturn())
84 info.GetReturnValue().Set(result.Return());
Dan Sinclair89d26c82017-10-26 12:21:28 -040085}
86
Dan Sinclairef299532017-10-26 16:48:30 -040087// static
Dan Sinclair89d26c82017-10-26 12:21:28 -040088void CJS_Global::putprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +000089 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -040090 v8::Local<v8::Value> value,
91 const v8::PropertyCallbackInfo<v8::Value>& info) {
Tom Sepez3f417872022-05-16 16:58:14 +000092 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
93 if (!pObj)
94 return;
95
96 CJS_Runtime* pRuntime = pObj->GetRuntime();
97 if (!pRuntime)
98 return;
99
100 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
101 CJS_Result result = pObj->SetProperty(pRuntime, bsProp, value);
102 if (result.HasError()) {
103 pRuntime->Error(
104 JSFormatErrorString("global", "PutProperty", result.Error()));
105 return;
106 }
107 info.GetReturnValue().Set(value);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400108}
109
Dan Sinclairef299532017-10-26 16:48:30 -0400110// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400111void CJS_Global::delprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000112 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400113 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
Tom Sepez3f417872022-05-16 16:58:14 +0000114 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
115 if (!pObj)
116 return;
117
118 ByteString bsProp = ByteStringFromV8Name(info.GetIsolate(), property);
119 if (pObj->DelProperty(bsProp))
120 info.GetReturnValue().Set(true);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400121}
122
Tom Sepez975aae52022-05-13 23:53:08 +0000123void CJS_Global::enumprop_static(
124 const v8::PropertyCallbackInfo<v8::Array>& info) {
Tom Sepez3f417872022-05-16 16:58:14 +0000125 auto pObj = JSGetObject<CJS_Global>(info.GetIsolate(), info.Holder());
126 if (!pObj)
127 return;
128
129 CJS_Runtime* pRuntime = pObj->GetRuntime();
130 if (!pRuntime)
131 return;
132
133 pObj->EnumProperties(pRuntime, info);
Tom Sepez975aae52022-05-13 23:53:08 +0000134}
135
Dan Sinclairef299532017-10-26 16:48:30 -0400136// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400137void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) {
138 pEngine->DefineObjAllProperties(
Dan Sinclairef299532017-10-26 16:48:30 -0400139 ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
Tom Sepez975aae52022-05-13 23:53:08 +0000140 CJS_Global::putprop_static, CJS_Global::delprop_static,
141 CJS_Global::enumprop_static);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400142}
143
Dan Sinclairef299532017-10-26 16:48:30 -0400144// static
Tom Sepezb4958712020-10-13 20:30:43 +0000145uint32_t CJS_Global::GetObjDefnID() {
Lei Zhangad1f7b42018-07-11 13:04:43 +0000146 return ObjDefnID;
147}
148
149// static
Dan Sinclairbef4d3e2017-10-26 16:49:38 -0400150void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine) {
151 ObjDefnID = pEngine->DefineObj("global", FXJSOBJTYPE_STATIC,
Dan Sinclair998fee32018-02-05 21:43:19 +0000152 JSConstructor<CJS_Global>, JSDestructor);
Tom Sepez8b4ddeb2018-06-11 15:55:17 +0000153 DefineMethods(pEngine, ObjDefnID, MethodSpecs);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400154 DefineAllProperties(pEngine);
155}
156
Tom Sepez36aae4f2018-06-04 19:44:37 +0000157CJS_Global::CJS_Global(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
Tom Sepez69bddfe2022-11-14 20:41:50 +0000158 : CJS_Object(pObject, pRuntime),
159 m_pGlobalData(CFX_GlobalData::GetRetainedInstance(nullptr)) {
Lei Zhang5b346562018-08-28 23:36:08 +0000160 UpdateGlobalPersistentVariables();
Tom Sepez83b259e2018-06-08 20:43:55 +0000161}
Dan Sinclair998fee32018-02-05 21:43:19 +0000162
Dan Sinclairf7435522018-02-05 22:27:22 +0000163CJS_Global::~CJS_Global() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700164 DestroyGlobalPersisitentVariables();
Tom Sepez16de5642023-01-27 00:11:50 +0000165 m_pGlobalData.ExtractAsDangling()->Release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700166}
167
Tom Sepez3f417872022-05-16 16:58:14 +0000168bool CJS_Global::HasProperty(const ByteString& propname) {
169 return pdfium::Contains(m_MapGlobal, propname);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700170}
171
Tom Sepez3f417872022-05-16 16:58:14 +0000172bool CJS_Global::DelProperty(const ByteString& propname) {
173 auto it = m_MapGlobal.find(propname);
Tom Sepeza7757232017-04-18 11:10:39 -0700174 if (it == m_MapGlobal.end())
Tom Sepez975aae52022-05-13 23:53:08 +0000175 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700176
tsepez4cf55152016-11-02 14:37:54 -0700177 it->second->bDeleted = true;
Tom Sepez975aae52022-05-13 23:53:08 +0000178 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700179}
180
Tom Sepez3a6d0582018-08-17 19:28:52 +0000181CJS_Result CJS_Global::GetProperty(CJS_Runtime* pRuntime,
Tom Sepez3f417872022-05-16 16:58:14 +0000182 const ByteString& propname) {
183 auto it = m_MapGlobal.find(propname);
dan sinclair5daf07a2017-10-24 21:46:57 -0400184 if (it == m_MapGlobal.end())
Tom Sepez3a6d0582018-08-17 19:28:52 +0000185 return CJS_Result::Success();
dan sinclaircbe23db2017-10-19 14:29:33 -0400186
187 JSGlobalData* pData = it->second.get();
dan sinclair5daf07a2017-10-24 21:46:57 -0400188 if (pData->bDeleted)
Tom Sepez3a6d0582018-08-17 19:28:52 +0000189 return CJS_Result::Success();
dan sinclaircbe23db2017-10-19 14:29:33 -0400190
191 switch (pData->nType) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000192 case CFX_Value::DataType::kNumber:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000193 return CJS_Result::Success(pRuntime->NewNumber(pData->dData));
Lei Zhang4709fa22020-06-02 20:02:26 +0000194 case CFX_Value::DataType::kBoolean:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000195 return CJS_Result::Success(pRuntime->NewBoolean(pData->bData));
Lei Zhang4709fa22020-06-02 20:02:26 +0000196 case CFX_Value::DataType::kString:
Tom Sepez10b10c42022-05-18 20:35:29 +0000197 return CJS_Result::Success(
198 pRuntime->NewString(pData->sData.AsStringView()));
Lei Zhang4709fa22020-06-02 20:02:26 +0000199 case CFX_Value::DataType::kObject:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000200 return CJS_Result::Success(
Dan Sinclair8f524d62017-10-25 13:30:31 -0400201 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
Lei Zhang4709fa22020-06-02 20:02:26 +0000202 case CFX_Value::DataType::kNull:
Tom Sepez3a6d0582018-08-17 19:28:52 +0000203 return CJS_Result::Success(pRuntime->NewNull());
dan sinclaircbe23db2017-10-19 14:29:33 -0400204 }
dan sinclaircbe23db2017-10-19 14:29:33 -0400205}
206
Tom Sepez3a6d0582018-08-17 19:28:52 +0000207CJS_Result CJS_Global::SetProperty(CJS_Runtime* pRuntime,
Tom Sepez3f417872022-05-16 16:58:14 +0000208 const ByteString& propname,
Dan Sinclairf7435522018-02-05 22:27:22 +0000209 v8::Local<v8::Value> vp) {
dan sinclair80435cb2017-10-24 21:40:24 -0400210 if (vp->IsNumber()) {
Tom Sepez3f417872022-05-16 16:58:14 +0000211 return SetGlobalVariables(propname, CFX_Value::DataType::kNumber,
Tom Sepez306ebab2018-12-03 22:12:55 +0000212 pRuntime->ToDouble(vp), false, ByteString(),
Dan Sinclair3cac3602017-10-24 15:15:27 -0400213 v8::Local<v8::Object>(), false);
214 }
dan sinclair80435cb2017-10-24 21:40:24 -0400215 if (vp->IsBoolean()) {
Tom Sepez3f417872022-05-16 16:58:14 +0000216 return SetGlobalVariables(propname, CFX_Value::DataType::kBoolean, 0,
Tom Sepez306ebab2018-12-03 22:12:55 +0000217 pRuntime->ToBoolean(vp), ByteString(),
Dan Sinclair3cac3602017-10-24 15:15:27 -0400218 v8::Local<v8::Object>(), false);
219 }
dan sinclair80435cb2017-10-24 21:40:24 -0400220 if (vp->IsString()) {
Tom Sepez3f417872022-05-16 16:58:14 +0000221 return SetGlobalVariables(propname, CFX_Value::DataType::kString, 0, false,
Tom Sepez10b10c42022-05-18 20:35:29 +0000222 pRuntime->ToByteString(vp),
Tom Sepez34dab072018-08-08 17:49:02 +0000223 v8::Local<v8::Object>(), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400224 }
dan sinclair80435cb2017-10-24 21:40:24 -0400225 if (vp->IsObject()) {
Tom Sepez3f417872022-05-16 16:58:14 +0000226 return SetGlobalVariables(propname, CFX_Value::DataType::kObject, 0, false,
Tom Sepez306ebab2018-12-03 22:12:55 +0000227 ByteString(), pRuntime->ToObject(vp), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400228 }
dan sinclair80435cb2017-10-24 21:40:24 -0400229 if (vp->IsNull()) {
Tom Sepez3f417872022-05-16 16:58:14 +0000230 return SetGlobalVariables(propname, CFX_Value::DataType::kNull, 0, false,
Tom Sepez306ebab2018-12-03 22:12:55 +0000231 ByteString(), v8::Local<v8::Object>(), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400232 }
dan sinclair80435cb2017-10-24 21:40:24 -0400233 if (vp->IsUndefined()) {
Tom Sepez3f417872022-05-16 16:58:14 +0000234 DelProperty(propname);
Tom Sepez3a6d0582018-08-17 19:28:52 +0000235 return CJS_Result::Success();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700236 }
Tom Sepez3a6d0582018-08-17 19:28:52 +0000237 return CJS_Result::Failure(JSMessage::kObjectTypeError);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238}
239
Tom Sepez975aae52022-05-13 23:53:08 +0000240void CJS_Global::EnumProperties(
241 CJS_Runtime* pRuntime,
242 const v8::PropertyCallbackInfo<v8::Array>& info) {
243 v8::Local<v8::Array> result = pRuntime->NewArray();
244 int idx = 0;
245 for (const auto& it : m_MapGlobal) {
246 if (it.second->bDeleted)
247 continue;
248 v8::Local<v8::Name> name = pRuntime->NewString(it.first.AsStringView());
249 pRuntime->PutArrayElement(result, idx, name);
250 ++idx;
251 }
252 info.GetReturnValue().Set(result);
253}
254
Tom Sepez3a6d0582018-08-17 19:28:52 +0000255CJS_Result CJS_Global::setPersistent(
dan sinclair80435cb2017-10-24 21:40:24 -0400256 CJS_Runtime* pRuntime,
Dan Sinclair8f524d62017-10-25 13:30:31 -0400257 const std::vector<v8::Local<v8::Value>>& params) {
258 if (params.size() != 2)
Tom Sepez3a6d0582018-08-17 19:28:52 +0000259 return CJS_Result::Failure(JSMessage::kParamError);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400260
Tom Sepez10b10c42022-05-18 20:35:29 +0000261 auto it = m_MapGlobal.find(pRuntime->ToByteString(params[0]));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400262 if (it == m_MapGlobal.end() || it->second->bDeleted)
Tom Sepez3a6d0582018-08-17 19:28:52 +0000263 return CJS_Result::Failure(JSMessage::kGlobalNotFoundError);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400264
dan sinclair80435cb2017-10-24 21:40:24 -0400265 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
Tom Sepez3a6d0582018-08-17 19:28:52 +0000266 return CJS_Result::Success();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700267}
268
Dan Sinclairf7435522018-02-05 22:27:22 +0000269void CJS_Global::UpdateGlobalPersistentVariables() {
Tom Sepez6ffd8402018-06-06 20:51:04 +0000270 CJS_Runtime* pRuntime = GetRuntime();
271 if (!pRuntime)
272 return;
tsepezb4694242016-08-15 16:44:55 -0700273
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700274 for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
Tom Sepez41d04e12018-10-30 22:07:36 +0000275 CFX_GlobalData::Element* pData = m_pGlobalData->GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276 switch (pData->data.nType) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000277 case CFX_Value::DataType::kNumber:
278 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kNumber,
Tom Sepez306ebab2018-12-03 22:12:55 +0000279 pData->data.dData, false, ByteString(),
Tom Sepezdf575cf2022-01-25 21:27:18 +0000280 v8::Local<v8::Object>(), pData->bPersistent);
Tom Sepezca610782018-12-13 18:01:04 +0000281 pRuntime->PutObjectProperty(ToV8Object(),
282 pData->data.sKey.AsStringView(),
283 pRuntime->NewNumber(pData->data.dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700284 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000285 case CFX_Value::DataType::kBoolean:
286 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kBoolean, 0,
Tom Sepez306ebab2018-12-03 22:12:55 +0000287 pData->data.bData == 1, ByteString(),
Tom Sepezdf575cf2022-01-25 21:27:18 +0000288 v8::Local<v8::Object>(), pData->bPersistent);
tsepeze6cf0132017-01-18 14:38:18 -0800289 pRuntime->PutObjectProperty(
Tom Sepezca610782018-12-13 18:01:04 +0000290 ToV8Object(), pData->data.sKey.AsStringView(),
tsepeze6cf0132017-01-18 14:38:18 -0800291 pRuntime->NewBoolean(pData->data.bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700292 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000293 case CFX_Value::DataType::kString:
294 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kString, 0,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700295 false, pData->data.sData, v8::Local<v8::Object>(),
Tom Sepezdf575cf2022-01-25 21:27:18 +0000296 pData->bPersistent);
tsepeze6cf0132017-01-18 14:38:18 -0800297 pRuntime->PutObjectProperty(
Tom Sepezca610782018-12-13 18:01:04 +0000298 ToV8Object(), pData->data.sKey.AsStringView(),
Tom Sepez10b10c42022-05-18 20:35:29 +0000299 pRuntime->NewString(pData->data.sData.AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700300 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000301 case CFX_Value::DataType::kObject: {
Tom Sepez9ad9a5f2018-02-07 21:07:24 +0000302 v8::Local<v8::Object> pObj = pRuntime->NewObject();
Tom Sepez63b2fc72017-08-14 16:24:29 -0700303 if (!pObj.IsEmpty()) {
304 PutObjectProperty(pObj, &pData->data);
Lei Zhang4709fa22020-06-02 20:02:26 +0000305 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kObject, 0,
Tom Sepezdf575cf2022-01-25 21:27:18 +0000306 false, ByteString(), pObj, pData->bPersistent);
Tom Sepezca610782018-12-13 18:01:04 +0000307 pRuntime->PutObjectProperty(ToV8Object(),
308 pData->data.sKey.AsStringView(), pObj);
Tom Sepez63b2fc72017-08-14 16:24:29 -0700309 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700310 } break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000311 case CFX_Value::DataType::kNull:
312 SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::kNull, 0,
Tom Sepez306ebab2018-12-03 22:12:55 +0000313 false, ByteString(), v8::Local<v8::Object>(),
Tom Sepezdf575cf2022-01-25 21:27:18 +0000314 pData->bPersistent);
Tom Sepez3ef02422018-11-26 23:52:33 +0000315 pRuntime->PutObjectProperty(
Tom Sepezca610782018-12-13 18:01:04 +0000316 ToV8Object(), pData->data.sKey.AsStringView(), pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700317 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700318 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700320}
321
Daniel Hosseinian7cf5ab62021-10-28 23:12:26 +0000322void CJS_Global::CommitGlobalPersisitentVariables() {
323 CJS_Runtime* pRuntime = GetRuntime();
324 if (!pRuntime)
325 return;
326
Tom Sepeza7757232017-04-18 11:10:39 -0700327 for (const auto& iter : m_MapGlobal) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400328 ByteString name = iter.first;
Tom Sepeza7757232017-04-18 11:10:39 -0700329 JSGlobalData* pData = iter.second.get();
Tom Sepez09d33bc2015-08-19 09:49:24 -0700330 if (pData->bDeleted) {
331 m_pGlobalData->DeleteGlobalVariable(name);
Tom Sepeza7757232017-04-18 11:10:39 -0700332 continue;
333 }
334 switch (pData->nType) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000335 case CFX_Value::DataType::kNumber:
Tom Sepeza7757232017-04-18 11:10:39 -0700336 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
337 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
338 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000339 case CFX_Value::DataType::kBoolean:
Tom Sepeza7757232017-04-18 11:10:39 -0700340 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
341 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
342 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000343 case CFX_Value::DataType::kString:
Tom Sepeza7757232017-04-18 11:10:39 -0700344 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
345 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
346 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000347 case CFX_Value::DataType::kObject: {
Dan Sinclairf7435522018-02-05 22:27:22 +0000348 v8::Local<v8::Object> obj =
Daniel Hosseinian7cf5ab62021-10-28 23:12:26 +0000349 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData);
Tom Sepez4f67a282020-12-17 18:43:12 +0000350 m_pGlobalData->SetGlobalVariableObject(name,
351 ObjectToArray(pRuntime, obj));
Tom Sepeza7757232017-04-18 11:10:39 -0700352 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
353 } break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000354 case CFX_Value::DataType::kNull:
Tom Sepeza7757232017-04-18 11:10:39 -0700355 m_pGlobalData->SetGlobalVariableNull(name);
356 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
357 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700358 }
359 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700360}
361
Tom Sepez4f67a282020-12-17 18:43:12 +0000362std::vector<std::unique_ptr<CFX_KeyValue>> CJS_Global::ObjectToArray(
Tom Sepez574ee372020-01-29 17:25:43 +0000363 CJS_Runtime* pRuntime,
Tom Sepez4f67a282020-12-17 18:43:12 +0000364 v8::Local<v8::Object> pObj) {
365 std::vector<std::unique_ptr<CFX_KeyValue>> array;
Ryan Harrison275e2602017-09-18 14:23:18 -0400366 std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
tsepezd0b6ed12016-08-11 19:50:57 -0700367 for (const auto& ws : pKeyList) {
Tom Sepezb4c95fe2018-11-27 01:09:44 +0000368 ByteString sKey = ws.ToUTF8();
Tom Sepezca610782018-12-13 18:01:04 +0000369 v8::Local<v8::Value> v =
370 pRuntime->GetObjectProperty(pObj, sKey.AsStringView());
Dan Sinclair3cac3602017-10-24 15:15:27 -0400371 if (v->IsNumber()) {
Tom Sepez31d722d2020-05-15 22:03:46 +0000372 auto pObjElement = std::make_unique<CFX_KeyValue>();
Lei Zhang4709fa22020-06-02 20:02:26 +0000373 pObjElement->nType = CFX_Value::DataType::kNumber;
Dan Sinclair3cac3602017-10-24 15:15:27 -0400374 pObjElement->sKey = sKey;
375 pObjElement->dData = pRuntime->ToDouble(v);
Tom Sepez4f67a282020-12-17 18:43:12 +0000376 array.push_back(std::move(pObjElement));
Dan Sinclair3cac3602017-10-24 15:15:27 -0400377 continue;
378 }
379 if (v->IsBoolean()) {
Tom Sepez31d722d2020-05-15 22:03:46 +0000380 auto pObjElement = std::make_unique<CFX_KeyValue>();
Lei Zhang4709fa22020-06-02 20:02:26 +0000381 pObjElement->nType = CFX_Value::DataType::kBoolean;
Dan Sinclair3cac3602017-10-24 15:15:27 -0400382 pObjElement->sKey = sKey;
383 pObjElement->dData = pRuntime->ToBoolean(v);
Tom Sepez4f67a282020-12-17 18:43:12 +0000384 array.push_back(std::move(pObjElement));
Dan Sinclair3cac3602017-10-24 15:15:27 -0400385 continue;
386 }
387 if (v->IsString()) {
Tom Sepez10b10c42022-05-18 20:35:29 +0000388 ByteString sValue = pRuntime->ToByteString(v);
Tom Sepez31d722d2020-05-15 22:03:46 +0000389 auto pObjElement = std::make_unique<CFX_KeyValue>();
Lei Zhang4709fa22020-06-02 20:02:26 +0000390 pObjElement->nType = CFX_Value::DataType::kString;
Dan Sinclair3cac3602017-10-24 15:15:27 -0400391 pObjElement->sKey = sKey;
392 pObjElement->sData = sValue;
Tom Sepez4f67a282020-12-17 18:43:12 +0000393 array.push_back(std::move(pObjElement));
Dan Sinclair3cac3602017-10-24 15:15:27 -0400394 continue;
395 }
396 if (v->IsObject()) {
Tom Sepez31d722d2020-05-15 22:03:46 +0000397 auto pObjElement = std::make_unique<CFX_KeyValue>();
Lei Zhang4709fa22020-06-02 20:02:26 +0000398 pObjElement->nType = CFX_Value::DataType::kObject;
Dan Sinclair3cac3602017-10-24 15:15:27 -0400399 pObjElement->sKey = sKey;
Tom Sepez4f67a282020-12-17 18:43:12 +0000400 pObjElement->objData = ObjectToArray(pRuntime, pRuntime->ToObject(v));
401 array.push_back(std::move(pObjElement));
Dan Sinclair3cac3602017-10-24 15:15:27 -0400402 continue;
403 }
404 if (v->IsNull()) {
Tom Sepez31d722d2020-05-15 22:03:46 +0000405 auto pObjElement = std::make_unique<CFX_KeyValue>();
Lei Zhang4709fa22020-06-02 20:02:26 +0000406 pObjElement->nType = CFX_Value::DataType::kNull;
Dan Sinclair3cac3602017-10-24 15:15:27 -0400407 pObjElement->sKey = sKey;
Tom Sepez4f67a282020-12-17 18:43:12 +0000408 array.push_back(std::move(pObjElement));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700409 }
410 }
Tom Sepez4f67a282020-12-17 18:43:12 +0000411 return array;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700412}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700413
Dan Sinclairf7435522018-02-05 22:27:22 +0000414void CJS_Global::PutObjectProperty(v8::Local<v8::Object> pObj,
Tom Sepez41d04e12018-10-30 22:07:36 +0000415 CFX_KeyValue* pData) {
Tom Sepez6ffd8402018-06-06 20:51:04 +0000416 CJS_Runtime* pRuntime = GetRuntime();
417 if (pRuntime)
418 return;
tsepezb4694242016-08-15 16:44:55 -0700419
Tom Sepez574ee372020-01-29 17:25:43 +0000420 for (size_t i = 0; i < pData->objData.size(); ++i) {
421 CFX_KeyValue* pObjData = pData->objData.at(i).get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700422 switch (pObjData->nType) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000423 case CFX_Value::DataType::kNumber:
Tom Sepezca610782018-12-13 18:01:04 +0000424 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
425 pRuntime->NewNumber(pObjData->dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700426 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000427 case CFX_Value::DataType::kBoolean:
Tom Sepezca610782018-12-13 18:01:04 +0000428 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
429 pRuntime->NewBoolean(pObjData->bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700430 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000431 case CFX_Value::DataType::kString:
tsepeze6cf0132017-01-18 14:38:18 -0800432 pRuntime->PutObjectProperty(
Tom Sepezca610782018-12-13 18:01:04 +0000433 pObj, pObjData->sKey.AsStringView(),
Tom Sepez10b10c42022-05-18 20:35:29 +0000434 pRuntime->NewString(pObjData->sData.AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700435 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000436 case CFX_Value::DataType::kObject: {
Tom Sepez9ad9a5f2018-02-07 21:07:24 +0000437 v8::Local<v8::Object> pNewObj = pRuntime->NewObject();
Tom Sepez63b2fc72017-08-14 16:24:29 -0700438 if (!pNewObj.IsEmpty()) {
439 PutObjectProperty(pNewObj, pObjData);
Tom Sepezca610782018-12-13 18:01:04 +0000440 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
441 pNewObj);
Tom Sepez63b2fc72017-08-14 16:24:29 -0700442 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700443 } break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000444 case CFX_Value::DataType::kNull:
Tom Sepezca610782018-12-13 18:01:04 +0000445 pRuntime->PutObjectProperty(pObj, pObjData->sKey.AsStringView(),
446 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700447 break;
448 }
449 }
450}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700451
Dan Sinclairf7435522018-02-05 22:27:22 +0000452void CJS_Global::DestroyGlobalPersisitentVariables() {
Tom Sepeza7757232017-04-18 11:10:39 -0700453 m_MapGlobal.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700454}
455
Tom Sepez3a6d0582018-08-17 19:28:52 +0000456CJS_Result CJS_Global::SetGlobalVariables(const ByteString& propname,
Tom Sepez4a463d52018-11-07 22:32:41 +0000457 CFX_Value::DataType nType,
Dan Sinclairf7435522018-02-05 22:27:22 +0000458 double dData,
459 bool bData,
460 const ByteString& sData,
461 v8::Local<v8::Object> pData,
462 bool bDefaultPersistent) {
tsepezb4c9f3f2016-04-13 15:41:21 -0700463 if (propname.IsEmpty())
Tom Sepez3a6d0582018-08-17 19:28:52 +0000464 return CJS_Result::Failure(JSMessage::kUnknownProperty);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700465
Tom Sepeza7757232017-04-18 11:10:39 -0700466 auto it = m_MapGlobal.find(propname);
467 if (it != m_MapGlobal.end()) {
468 JSGlobalData* pTemp = it->second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700469 if (pTemp->bDeleted || pTemp->nType != nType) {
470 pTemp->dData = 0;
Anton Bikineev7ac13342022-01-24 21:25:15 +0000471 pTemp->bData = false;
Lei Zhangfe2cd4d2017-11-22 20:04:12 +0000472 pTemp->sData.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700473 pTemp->nType = nType;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700474 }
tsepez4cf55152016-11-02 14:37:54 -0700475 pTemp->bDeleted = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700476 switch (nType) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000477 case CFX_Value::DataType::kNumber:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700478 pTemp->dData = dData;
Tom Sepeza7757232017-04-18 11:10:39 -0700479 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000480 case CFX_Value::DataType::kBoolean:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700481 pTemp->bData = bData;
Tom Sepeza7757232017-04-18 11:10:39 -0700482 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000483 case CFX_Value::DataType::kString:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700484 pTemp->sData = sData;
Tom Sepeza7757232017-04-18 11:10:39 -0700485 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000486 case CFX_Value::DataType::kObject:
Tom Sepez371379d2015-11-06 08:29:39 -0800487 pTemp->pData.Reset(pData->GetIsolate(), pData);
Tom Sepeza7757232017-04-18 11:10:39 -0700488 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000489 case CFX_Value::DataType::kNull:
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700490 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700491 }
Tom Sepez3a6d0582018-08-17 19:28:52 +0000492 return CJS_Result::Success();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700493 }
494
Tom Sepez31d722d2020-05-15 22:03:46 +0000495 auto pNewData = std::make_unique<JSGlobalData>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700496 switch (nType) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000497 case CFX_Value::DataType::kNumber:
498 pNewData->nType = CFX_Value::DataType::kNumber;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700499 pNewData->dData = dData;
500 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700501 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000502 case CFX_Value::DataType::kBoolean:
503 pNewData->nType = CFX_Value::DataType::kBoolean;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700504 pNewData->bData = bData;
505 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700506 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000507 case CFX_Value::DataType::kString:
508 pNewData->nType = CFX_Value::DataType::kString;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700509 pNewData->sData = sData;
510 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700511 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000512 case CFX_Value::DataType::kObject:
513 pNewData->nType = CFX_Value::DataType::kObject;
Tom Sepez371379d2015-11-06 08:29:39 -0800514 pNewData->pData.Reset(pData->GetIsolate(), pData);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700515 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700516 break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000517 case CFX_Value::DataType::kNull:
518 pNewData->nType = CFX_Value::DataType::kNull;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700519 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700520 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700521 }
Tom Sepeza7757232017-04-18 11:10:39 -0700522 m_MapGlobal[propname] = std::move(pNewData);
Tom Sepez3a6d0582018-08-17 19:28:52 +0000523 return CJS_Result::Success();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700524}