blob: 95124ff84d7964f1b4d709b6929d639b9ab13234 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
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 <map>
10#include <memory>
Tom Sepeza7757232017-04-18 11:10:39 -070011#include <utility>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050012#include <vector>
13
Dan Sinclaircfb19442017-04-20 13:13:04 -040014#include "core/fxcrt/fx_extension.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000015#include "fxjs/JS_Define.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000016#include "fxjs/cjs_event_context.h"
17#include "fxjs/cjs_eventhandler.h"
Dan Sinclaira3254622017-10-30 20:24:14 +000018#include "fxjs/cjs_globaldata.h"
19#include "fxjs/cjs_keyvalue.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000020#include "fxjs/cjs_object.h"
21#include "fxjs/js_resources.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070022
Dan Sinclair4b172c42017-10-23 11:22:31 -040023namespace {
24
Dan Sinclair8f524d62017-10-25 13:30:31 -040025WideString PropFromV8Prop(v8::Local<v8::String> property) {
26 v8::String::Utf8Value utf8_value(property);
27 return WideString::FromUTF8(ByteStringView(*utf8_value, utf8_value.length()));
28}
29
Dan Sinclair4b172c42017-10-23 11:22:31 -040030template <class Alt>
31void JSSpecialPropQuery(const char*,
32 v8::Local<v8::String> property,
33 const v8::PropertyCallbackInfo<v8::Integer>& info) {
34 CJS_Runtime* pRuntime =
35 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
36 if (!pRuntime)
37 return;
38
39 CJS_Object* pJSObj =
40 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
41 if (!pJSObj)
42 return;
43
44 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -040045 CJS_Return result = pObj->QueryProperty(PropFromV8Prop(property).c_str());
46 info.GetReturnValue().Set(!result.HasError() ? 4 : 0);
Dan Sinclair4b172c42017-10-23 11:22:31 -040047}
48
49template <class Alt>
50void JSSpecialPropGet(const char* class_name,
51 v8::Local<v8::String> property,
52 const v8::PropertyCallbackInfo<v8::Value>& info) {
53 CJS_Runtime* pRuntime =
54 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
55 if (!pRuntime)
56 return;
57
58 CJS_Object* pJSObj =
59 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
60 if (!pJSObj)
61 return;
62
63 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -040064 CJS_Return result =
65 pObj->GetProperty(pRuntime, PropFromV8Prop(property).c_str());
66 if (result.HasError()) {
67 pRuntime->Error(
68 JSFormatErrorString(class_name, "GetProperty", result.Error()));
Dan Sinclair4b172c42017-10-23 11:22:31 -040069 return;
70 }
Dan Sinclair8f524d62017-10-25 13:30:31 -040071
72 if (result.HasReturn())
73 info.GetReturnValue().Set(result.Return());
Dan Sinclair4b172c42017-10-23 11:22:31 -040074}
75
76template <class Alt>
77void JSSpecialPropPut(const char* class_name,
78 v8::Local<v8::String> property,
79 v8::Local<v8::Value> value,
80 const v8::PropertyCallbackInfo<v8::Value>& info) {
81 CJS_Runtime* pRuntime =
82 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
83 if (!pRuntime)
84 return;
85
86 CJS_Object* pJSObj =
87 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
88 if (!pJSObj)
89 return;
90
91 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -040092 CJS_Return result =
93 pObj->SetProperty(pRuntime, PropFromV8Prop(property).c_str(), value);
94 if (result.HasError()) {
95 pRuntime->Error(
96 JSFormatErrorString(class_name, "PutProperty", result.Error()));
97 }
Dan Sinclair4b172c42017-10-23 11:22:31 -040098}
99
100template <class Alt>
101void JSSpecialPropDel(const char* class_name,
102 v8::Local<v8::String> property,
103 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
104 CJS_Runtime* pRuntime =
105 CJS_Runtime::CurrentRuntimeFromIsolate(info.GetIsolate());
106 if (!pRuntime)
107 return;
108
109 CJS_Object* pJSObj =
110 static_cast<CJS_Object*>(pRuntime->GetObjectPrivate(info.Holder()));
111 if (!pJSObj)
112 return;
113
114 Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
Dan Sinclair8f524d62017-10-25 13:30:31 -0400115 CJS_Return result =
116 pObj->DelProperty(pRuntime, PropFromV8Prop(property).c_str());
117 if (result.HasError()) {
118 // TODO(dsinclair): Should this set the pRuntime->Error result?
Henrique Nakashima11506302017-12-06 22:09:40 +0000119 // ByteString cbName =
120 // ByteString::Format("%s.%s", class_name, "DelProperty");
Dan Sinclair4b172c42017-10-23 11:22:31 -0400121 }
122}
123
124struct JSGlobalData {
125 JSGlobalData();
126 ~JSGlobalData();
127
128 JS_GlobalDataType nType;
129 double dData;
130 bool bData;
131 ByteString sData;
132 v8::Global<v8::Object> pData;
133 bool bPersistent;
134 bool bDeleted;
135};
136
137class JSGlobalAlternate : public CJS_EmbedObj {
138 public:
139 explicit JSGlobalAlternate(CJS_Object* pJSObject);
140 ~JSGlobalAlternate() override;
141
Dan Sinclair8f524d62017-10-25 13:30:31 -0400142 CJS_Return setPersistent(CJS_Runtime* pRuntime,
143 const std::vector<v8::Local<v8::Value>>& params);
144 CJS_Return QueryProperty(const wchar_t* propname);
145 CJS_Return GetProperty(CJS_Runtime* pRuntime, const wchar_t* propname);
146 CJS_Return SetProperty(CJS_Runtime* pRuntime,
147 const wchar_t* propname,
148 v8::Local<v8::Value> vp);
149 CJS_Return DelProperty(CJS_Runtime* pRuntime, const wchar_t* propname);
Dan Sinclair4b172c42017-10-23 11:22:31 -0400150 void Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv);
151
152 private:
153 void UpdateGlobalPersistentVariables();
154 void CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime);
155 void DestroyGlobalPersisitentVariables();
Dan Sinclair8f524d62017-10-25 13:30:31 -0400156 CJS_Return SetGlobalVariables(const ByteString& propname,
157 JS_GlobalDataType nType,
158 double dData,
159 bool bData,
160 const ByteString& sData,
161 v8::Local<v8::Object> pData,
162 bool bDefaultPersistent);
Dan Sinclair4b172c42017-10-23 11:22:31 -0400163 void ObjectToArray(CJS_Runtime* pRuntime,
164 v8::Local<v8::Object> pObj,
165 CJS_GlobalVariableArray& array);
166 void PutObjectProperty(v8::Local<v8::Object> obj, CJS_KeyValue* pData);
167
168 std::map<ByteString, std::unique_ptr<JSGlobalData>> m_MapGlobal;
169 WideString m_sFilePath;
170 CJS_GlobalData* m_pGlobalData;
171 CPDFSDK_FormFillEnvironment::ObservedPtr m_pFormFillEnv;
172};
173
174} // namespace
175
Dan Sinclairc94a7932017-10-26 16:48:57 -0400176const JSMethodSpec CJS_Global::MethodSpecs[] = {
Tom Sepez9b99b632017-02-21 15:05:57 -0800177 {"setPersistent", setPersistent_static},
Tom Sepez04557b82017-02-16 09:43:10 -0800178 {0, 0}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700179
Dan Sinclairef299532017-10-26 16:48:30 -0400180int CJS_Global::ObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700181
Dan Sinclair4b172c42017-10-23 11:22:31 -0400182// static
183void CJS_Global::setPersistent_static(
184 const v8::FunctionCallbackInfo<v8::Value>& info) {
185 JSMethod<JSGlobalAlternate, &JSGlobalAlternate::setPersistent>(
186 "setPersistent", "global", info);
187}
188
Dan Sinclairef299532017-10-26 16:48:30 -0400189// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400190void CJS_Global::queryprop_static(
191 v8::Local<v8::String> property,
192 const v8::PropertyCallbackInfo<v8::Integer>& info) {
193 JSSpecialPropQuery<JSGlobalAlternate>("global", property, info);
194}
195
Dan Sinclairef299532017-10-26 16:48:30 -0400196// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400197void CJS_Global::getprop_static(
198 v8::Local<v8::String> property,
199 const v8::PropertyCallbackInfo<v8::Value>& info) {
200 JSSpecialPropGet<JSGlobalAlternate>("global", property, info);
201}
202
Dan Sinclairef299532017-10-26 16:48:30 -0400203// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400204void CJS_Global::putprop_static(
205 v8::Local<v8::String> property,
206 v8::Local<v8::Value> value,
207 const v8::PropertyCallbackInfo<v8::Value>& info) {
208 JSSpecialPropPut<JSGlobalAlternate>("global", property, value, info);
209}
210
Dan Sinclairef299532017-10-26 16:48:30 -0400211// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400212void CJS_Global::delprop_static(
213 v8::Local<v8::String> property,
214 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
215 JSSpecialPropDel<JSGlobalAlternate>("global", property, info);
216}
217
Dan Sinclairef299532017-10-26 16:48:30 -0400218// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400219void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) {
220 pEngine->DefineObjAllProperties(
Dan Sinclairef299532017-10-26 16:48:30 -0400221 ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400222 CJS_Global::putprop_static, CJS_Global::delprop_static);
223}
224
Dan Sinclairef299532017-10-26 16:48:30 -0400225// static
Dan Sinclairbef4d3e2017-10-26 16:49:38 -0400226void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine) {
227 ObjDefnID = pEngine->DefineObj("global", FXJSOBJTYPE_STATIC,
Dan Sinclairef299532017-10-26 16:48:30 -0400228 JSConstructor<CJS_Global, JSGlobalAlternate>,
229 JSDestructor<CJS_Global>);
230 DefineMethods(pEngine, ObjDefnID, MethodSpecs);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400231 DefineAllProperties(pEngine);
232}
233
Dan Sinclairef299532017-10-26 16:48:30 -0400234void CJS_Global::InitInstance(IJS_Runtime* pIRuntime) {
235 CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
236 JSGlobalAlternate* pGlobal =
237 static_cast<JSGlobalAlternate*>(GetEmbedObject());
238 pGlobal->Initial(pRuntime->GetFormFillEnv());
239}
240
weili625ad662016-06-15 11:21:33 -0700241JSGlobalData::JSGlobalData()
weili47228ac2016-07-20 10:35:31 -0700242 : nType(JS_GlobalDataType::NUMBER),
weili625ad662016-06-15 11:21:33 -0700243 dData(0),
tsepez4cf55152016-11-02 14:37:54 -0700244 bData(false),
weili625ad662016-06-15 11:21:33 -0700245 sData(""),
tsepez4cf55152016-11-02 14:37:54 -0700246 bPersistent(false),
247 bDeleted(false) {}
weili625ad662016-06-15 11:21:33 -0700248
249JSGlobalData::~JSGlobalData() {
250 pData.Reset();
251}
252
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700253JSGlobalAlternate::JSGlobalAlternate(CJS_Object* pJSObject)
dsinclair8779fa82016-10-12 12:05:44 -0700254 : CJS_EmbedObj(pJSObject), m_pFormFillEnv(nullptr) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700256JSGlobalAlternate::~JSGlobalAlternate() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700257 DestroyGlobalPersisitentVariables();
Tom Sepezf4583622015-09-14 15:06:53 -0700258 m_pGlobalData->Release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700259}
260
dsinclair8779fa82016-10-12 12:05:44 -0700261void JSGlobalAlternate::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
Tom Sepez77f6d0f2017-02-23 12:14:10 -0800262 m_pFormFillEnv.Reset(pFormFillEnv);
dsinclair8779fa82016-10-12 12:05:44 -0700263 m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700264 UpdateGlobalPersistentVariables();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700265}
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700266
Dan Sinclair8f524d62017-10-25 13:30:31 -0400267CJS_Return JSGlobalAlternate::QueryProperty(const wchar_t* propname) {
268 return CJS_Return(WideString(propname) != L"setPersistent");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700269}
270
Dan Sinclair8f524d62017-10-25 13:30:31 -0400271CJS_Return JSGlobalAlternate::DelProperty(CJS_Runtime* pRuntime,
272 const wchar_t* propname) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400273 auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
Tom Sepeza7757232017-04-18 11:10:39 -0700274 if (it == m_MapGlobal.end())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400275 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276
tsepez4cf55152016-11-02 14:37:54 -0700277 it->second->bDeleted = true;
Dan Sinclair8f524d62017-10-25 13:30:31 -0400278 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700279}
280
Dan Sinclair8f524d62017-10-25 13:30:31 -0400281CJS_Return JSGlobalAlternate::GetProperty(CJS_Runtime* pRuntime,
282 const wchar_t* propname) {
dan sinclaircbe23db2017-10-19 14:29:33 -0400283 auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
dan sinclair5daf07a2017-10-24 21:46:57 -0400284 if (it == m_MapGlobal.end())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400285 return CJS_Return(true);
dan sinclaircbe23db2017-10-19 14:29:33 -0400286
287 JSGlobalData* pData = it->second.get();
dan sinclair5daf07a2017-10-24 21:46:57 -0400288 if (pData->bDeleted)
Dan Sinclair8f524d62017-10-25 13:30:31 -0400289 return CJS_Return(true);
dan sinclaircbe23db2017-10-19 14:29:33 -0400290
291 switch (pData->nType) {
292 case JS_GlobalDataType::NUMBER:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400293 return CJS_Return(pRuntime->NewNumber(pData->dData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400294 case JS_GlobalDataType::BOOLEAN:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400295 return CJS_Return(pRuntime->NewBoolean(pData->bData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400296 case JS_GlobalDataType::STRING:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400297 return CJS_Return(pRuntime->NewString(
Dan Sinclaire4974922017-10-24 09:36:16 -0400298 WideString::FromLocal(pData->sData.c_str()).c_str()));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400299 case JS_GlobalDataType::OBJECT:
300 return CJS_Return(
301 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400302 case JS_GlobalDataType::NULLOBJ:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400303 return CJS_Return(pRuntime->NewNull());
dan sinclaircbe23db2017-10-19 14:29:33 -0400304 default:
305 break;
306 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400307 return CJS_Return(false);
dan sinclaircbe23db2017-10-19 14:29:33 -0400308}
309
Dan Sinclair8f524d62017-10-25 13:30:31 -0400310CJS_Return JSGlobalAlternate::SetProperty(CJS_Runtime* pRuntime,
311 const wchar_t* propname,
312 v8::Local<v8::Value> vp) {
dan sinclaircbe23db2017-10-19 14:29:33 -0400313 ByteString sPropName = ByteString::FromUnicode(propname);
dan sinclair80435cb2017-10-24 21:40:24 -0400314 if (vp->IsNumber()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400315 return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER,
dan sinclair80435cb2017-10-24 21:40:24 -0400316 pRuntime->ToDouble(vp), false, "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400317 v8::Local<v8::Object>(), false);
318 }
dan sinclair80435cb2017-10-24 21:40:24 -0400319 if (vp->IsBoolean()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400320 return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0,
dan sinclair80435cb2017-10-24 21:40:24 -0400321 pRuntime->ToBoolean(vp), "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400322 v8::Local<v8::Object>(), false);
323 }
dan sinclair80435cb2017-10-24 21:40:24 -0400324 if (vp->IsString()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400325 return SetGlobalVariables(
326 sPropName, JS_GlobalDataType::STRING, 0, false,
dan sinclair80435cb2017-10-24 21:40:24 -0400327 ByteString::FromUnicode(pRuntime->ToWideString(vp)),
Dan Sinclair3cac3602017-10-24 15:15:27 -0400328 v8::Local<v8::Object>(), false);
329 }
dan sinclair80435cb2017-10-24 21:40:24 -0400330 if (vp->IsObject()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400331 return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0, false,
dan sinclair80435cb2017-10-24 21:40:24 -0400332 "", pRuntime->ToObject(vp), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400333 }
dan sinclair80435cb2017-10-24 21:40:24 -0400334 if (vp->IsNull()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400335 return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0, false,
336 "", v8::Local<v8::Object>(), false);
337 }
dan sinclair80435cb2017-10-24 21:40:24 -0400338 if (vp->IsUndefined()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400339 DelProperty(pRuntime, propname);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400340 return CJS_Return(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400342 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700343}
344
Dan Sinclair8f524d62017-10-25 13:30:31 -0400345CJS_Return JSGlobalAlternate::setPersistent(
dan sinclair80435cb2017-10-24 21:40:24 -0400346 CJS_Runtime* pRuntime,
Dan Sinclair8f524d62017-10-25 13:30:31 -0400347 const std::vector<v8::Local<v8::Value>>& params) {
348 if (params.size() != 2)
Dan Sinclaird6e9cfa2017-10-30 21:19:42 +0000349 return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400350
Dan Sinclair1b2a18e2017-10-24 13:56:29 -0400351 auto it = m_MapGlobal.find(
dan sinclair80435cb2017-10-24 21:40:24 -0400352 ByteString::FromUnicode(pRuntime->ToWideString(params[0])));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400353 if (it == m_MapGlobal.end() || it->second->bDeleted)
Dan Sinclaird6e9cfa2017-10-30 21:19:42 +0000354 return CJS_Return(JSGetStringFromID(JSMessage::kGlobalNotFoundError));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400355
dan sinclair80435cb2017-10-24 21:40:24 -0400356 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400357 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700358}
359
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700360void JSGlobalAlternate::UpdateGlobalPersistentVariables() {
tsepezb4694242016-08-15 16:44:55 -0700361 CJS_Runtime* pRuntime =
362 static_cast<CJS_Runtime*>(CFXJS_Engine::CurrentEngineFromIsolate(
363 m_pJSObject->ToV8Object()->GetIsolate()));
364
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700365 for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
366 CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700367 switch (pData->data.nType) {
weili47228ac2016-07-20 10:35:31 -0700368 case JS_GlobalDataType::NUMBER:
369 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 pData->data.dData, false, "",
371 v8::Local<v8::Object>(), pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800372 pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
373 pData->data.sKey.UTF8Decode(),
374 pRuntime->NewNumber(pData->data.dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700375 break;
weili47228ac2016-07-20 10:35:31 -0700376 case JS_GlobalDataType::BOOLEAN:
377 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0,
tsepeze6cf0132017-01-18 14:38:18 -0800378 pData->data.bData == 1, "", v8::Local<v8::Object>(),
379 pData->bPersistent == 1);
380 pRuntime->PutObjectProperty(
381 m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
382 pRuntime->NewBoolean(pData->data.bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 break;
weili47228ac2016-07-20 10:35:31 -0700384 case JS_GlobalDataType::STRING:
385 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700386 false, pData->data.sData, v8::Local<v8::Object>(),
387 pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800388 pRuntime->PutObjectProperty(
389 m_pJSObject->ToV8Object(), pData->data.sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400390 pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700391 break;
weili47228ac2016-07-20 10:35:31 -0700392 case JS_GlobalDataType::OBJECT: {
tsepezb4694242016-08-15 16:44:55 -0700393 v8::Local<v8::Object> pObj = pRuntime->NewFxDynamicObj(-1);
Tom Sepez63b2fc72017-08-14 16:24:29 -0700394 if (!pObj.IsEmpty()) {
395 PutObjectProperty(pObj, &pData->data);
396 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0,
397 false, "", pObj, pData->bPersistent == 1);
398 pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
399 pData->data.sKey.UTF8Decode(), pObj);
400 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700401 } break;
weili47228ac2016-07-20 10:35:31 -0700402 case JS_GlobalDataType::NULLOBJ:
403 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0,
404 false, "", v8::Local<v8::Object>(),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700405 pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800406 pRuntime->PutObjectProperty(m_pJSObject->ToV8Object(),
407 pData->data.sKey.UTF8Decode(),
408 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700409 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700410 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700411 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700412}
413
Tom Sepezb1670b52017-02-16 17:01:00 -0800414void JSGlobalAlternate::CommitGlobalPersisitentVariables(
415 CJS_Runtime* pRuntime) {
Tom Sepeza7757232017-04-18 11:10:39 -0700416 for (const auto& iter : m_MapGlobal) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400417 ByteString name = iter.first;
Tom Sepeza7757232017-04-18 11:10:39 -0700418 JSGlobalData* pData = iter.second.get();
Tom Sepez09d33bc2015-08-19 09:49:24 -0700419 if (pData->bDeleted) {
420 m_pGlobalData->DeleteGlobalVariable(name);
Tom Sepeza7757232017-04-18 11:10:39 -0700421 continue;
422 }
423 switch (pData->nType) {
424 case JS_GlobalDataType::NUMBER:
425 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
426 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
427 break;
428 case JS_GlobalDataType::BOOLEAN:
429 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
430 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
431 break;
432 case JS_GlobalDataType::STRING:
433 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
434 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
435 break;
436 case JS_GlobalDataType::OBJECT: {
437 CJS_GlobalVariableArray array;
438 v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(
439 GetJSObject()->GetIsolate(), pData->pData);
440 ObjectToArray(pRuntime, obj, array);
441 m_pGlobalData->SetGlobalVariableObject(name, array);
442 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
443 } break;
444 case JS_GlobalDataType::NULLOBJ:
445 m_pGlobalData->SetGlobalVariableNull(name);
446 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
447 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 }
449 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700450}
451
Tom Sepezb1670b52017-02-16 17:01:00 -0800452void JSGlobalAlternate::ObjectToArray(CJS_Runtime* pRuntime,
Tom Sepez67fd5df2015-10-08 12:24:19 -0700453 v8::Local<v8::Object> pObj,
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700454 CJS_GlobalVariableArray& array) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400455 std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
tsepezd0b6ed12016-08-11 19:50:57 -0700456 for (const auto& ws : pKeyList) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400457 ByteString sKey = ws.UTF8Encode();
tsepezb4694242016-08-15 16:44:55 -0700458 v8::Local<v8::Value> v = pRuntime->GetObjectProperty(pObj, ws);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400459 if (v->IsNumber()) {
460 CJS_KeyValue* pObjElement = new CJS_KeyValue;
461 pObjElement->nType = JS_GlobalDataType::NUMBER;
462 pObjElement->sKey = sKey;
463 pObjElement->dData = pRuntime->ToDouble(v);
464 array.Add(pObjElement);
465 continue;
466 }
467 if (v->IsBoolean()) {
468 CJS_KeyValue* pObjElement = new CJS_KeyValue;
469 pObjElement->nType = JS_GlobalDataType::BOOLEAN;
470 pObjElement->sKey = sKey;
471 pObjElement->dData = pRuntime->ToBoolean(v);
472 array.Add(pObjElement);
473 continue;
474 }
475 if (v->IsString()) {
476 ByteString sValue = ByteString::FromUnicode(pRuntime->ToWideString(v));
477 CJS_KeyValue* pObjElement = new CJS_KeyValue;
478 pObjElement->nType = JS_GlobalDataType::STRING;
479 pObjElement->sKey = sKey;
480 pObjElement->sData = sValue;
481 array.Add(pObjElement);
482 continue;
483 }
484 if (v->IsObject()) {
485 CJS_KeyValue* pObjElement = new CJS_KeyValue;
486 pObjElement->nType = JS_GlobalDataType::OBJECT;
487 pObjElement->sKey = sKey;
488 ObjectToArray(pRuntime, pRuntime->ToObject(v), pObjElement->objData);
489 array.Add(pObjElement);
490 continue;
491 }
492 if (v->IsNull()) {
493 CJS_KeyValue* pObjElement = new CJS_KeyValue;
494 pObjElement->nType = JS_GlobalDataType::NULLOBJ;
495 pObjElement->sKey = sKey;
496 array.Add(pObjElement);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700497 }
498 }
499}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700500
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700501void JSGlobalAlternate::PutObjectProperty(v8::Local<v8::Object> pObj,
502 CJS_KeyValue* pData) {
tsepezb4694242016-08-15 16:44:55 -0700503 CJS_Runtime* pRuntime = CJS_Runtime::CurrentRuntimeFromIsolate(
504 m_pJSObject->ToV8Object()->GetIsolate());
505
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700506 for (int i = 0, sz = pData->objData.Count(); i < sz; i++) {
507 CJS_KeyValue* pObjData = pData->objData.GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700508 switch (pObjData->nType) {
weili47228ac2016-07-20 10:35:31 -0700509 case JS_GlobalDataType::NUMBER:
tsepeze6cf0132017-01-18 14:38:18 -0800510 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
511 pRuntime->NewNumber(pObjData->dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700512 break;
weili47228ac2016-07-20 10:35:31 -0700513 case JS_GlobalDataType::BOOLEAN:
tsepeze6cf0132017-01-18 14:38:18 -0800514 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
515 pRuntime->NewBoolean(pObjData->bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700516 break;
weili47228ac2016-07-20 10:35:31 -0700517 case JS_GlobalDataType::STRING:
tsepeze6cf0132017-01-18 14:38:18 -0800518 pRuntime->PutObjectProperty(
519 pObj, pObjData->sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400520 pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700521 break;
weili47228ac2016-07-20 10:35:31 -0700522 case JS_GlobalDataType::OBJECT: {
tsepezb4694242016-08-15 16:44:55 -0700523 v8::Local<v8::Object> pNewObj = pRuntime->NewFxDynamicObj(-1);
Tom Sepez63b2fc72017-08-14 16:24:29 -0700524 if (!pNewObj.IsEmpty()) {
525 PutObjectProperty(pNewObj, pObjData);
526 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
527 pNewObj);
528 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700529 } break;
weili47228ac2016-07-20 10:35:31 -0700530 case JS_GlobalDataType::NULLOBJ:
tsepeze6cf0132017-01-18 14:38:18 -0800531 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
532 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700533 break;
534 }
535 }
536}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700537
Tom Sepez7dc5cc12015-08-17 12:15:26 -0700538void JSGlobalAlternate::DestroyGlobalPersisitentVariables() {
Tom Sepeza7757232017-04-18 11:10:39 -0700539 m_MapGlobal.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700540}
541
Dan Sinclair8f524d62017-10-25 13:30:31 -0400542CJS_Return JSGlobalAlternate::SetGlobalVariables(const ByteString& propname,
543 JS_GlobalDataType nType,
544 double dData,
545 bool bData,
546 const ByteString& sData,
547 v8::Local<v8::Object> pData,
548 bool bDefaultPersistent) {
tsepezb4c9f3f2016-04-13 15:41:21 -0700549 if (propname.IsEmpty())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400550 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700551
Tom Sepeza7757232017-04-18 11:10:39 -0700552 auto it = m_MapGlobal.find(propname);
553 if (it != m_MapGlobal.end()) {
554 JSGlobalData* pTemp = it->second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700555 if (pTemp->bDeleted || pTemp->nType != nType) {
556 pTemp->dData = 0;
557 pTemp->bData = 0;
Lei Zhangfe2cd4d2017-11-22 20:04:12 +0000558 pTemp->sData.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 pTemp->nType = nType;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700560 }
tsepez4cf55152016-11-02 14:37:54 -0700561 pTemp->bDeleted = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700562 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700563 case JS_GlobalDataType::NUMBER:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700564 pTemp->dData = dData;
Tom Sepeza7757232017-04-18 11:10:39 -0700565 break;
566 case JS_GlobalDataType::BOOLEAN:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700567 pTemp->bData = bData;
Tom Sepeza7757232017-04-18 11:10:39 -0700568 break;
569 case JS_GlobalDataType::STRING:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700570 pTemp->sData = sData;
Tom Sepeza7757232017-04-18 11:10:39 -0700571 break;
572 case JS_GlobalDataType::OBJECT:
Tom Sepez371379d2015-11-06 08:29:39 -0800573 pTemp->pData.Reset(pData->GetIsolate(), pData);
Tom Sepeza7757232017-04-18 11:10:39 -0700574 break;
weili47228ac2016-07-20 10:35:31 -0700575 case JS_GlobalDataType::NULLOBJ:
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700576 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700577 default:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400578 return CJS_Return(false);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700579 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400580 return CJS_Return(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700581 }
582
Tom Sepeza7757232017-04-18 11:10:39 -0700583 auto pNewData = pdfium::MakeUnique<JSGlobalData>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700584 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700585 case JS_GlobalDataType::NUMBER:
weili47228ac2016-07-20 10:35:31 -0700586 pNewData->nType = JS_GlobalDataType::NUMBER;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700587 pNewData->dData = dData;
588 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700589 break;
590 case JS_GlobalDataType::BOOLEAN:
weili47228ac2016-07-20 10:35:31 -0700591 pNewData->nType = JS_GlobalDataType::BOOLEAN;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700592 pNewData->bData = bData;
593 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700594 break;
595 case JS_GlobalDataType::STRING:
weili47228ac2016-07-20 10:35:31 -0700596 pNewData->nType = JS_GlobalDataType::STRING;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700597 pNewData->sData = sData;
598 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700599 break;
600 case JS_GlobalDataType::OBJECT:
weili47228ac2016-07-20 10:35:31 -0700601 pNewData->nType = JS_GlobalDataType::OBJECT;
Tom Sepez371379d2015-11-06 08:29:39 -0800602 pNewData->pData.Reset(pData->GetIsolate(), pData);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700603 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700604 break;
605 case JS_GlobalDataType::NULLOBJ:
weili47228ac2016-07-20 10:35:31 -0700606 pNewData->nType = JS_GlobalDataType::NULLOBJ;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700607 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700608 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700609 default:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400610 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700611 }
Tom Sepeza7757232017-04-18 11:10:39 -0700612 m_MapGlobal[propname] = std::move(pNewData);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400613 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700614}