blob: 9a1f541212e87010bef2de8dcd5fedc4a450bbfb [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/cjs_event_context.h"
16#include "fxjs/cjs_eventhandler.h"
Dan Sinclaira3254622017-10-30 20:24:14 +000017#include "fxjs/cjs_globaldata.h"
18#include "fxjs/cjs_keyvalue.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000019#include "fxjs/cjs_object.h"
Tom Sepez221f0b32018-06-04 22:11:27 +000020#include "fxjs/js_define.h"
Dan Sinclaire0345a42017-10-30 20:20:42 +000021#include "fxjs/js_resources.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070022
Dan Sinclair4b172c42017-10-23 11:22:31 -040023namespace {
24
Adam Klein4c451ba2018-01-17 21:06:27 +000025WideString PropFromV8Prop(v8::Isolate* pIsolate,
26 v8::Local<v8::String> property) {
27 v8::String::Utf8Value utf8_value(pIsolate, property);
Dan Sinclair8f524d62017-10-25 13:30:31 -040028 return WideString::FromUTF8(ByteStringView(*utf8_value, utf8_value.length()));
29}
30
Dan Sinclair4b172c42017-10-23 11:22:31 -040031template <class Alt>
32void JSSpecialPropQuery(const char*,
33 v8::Local<v8::String> property,
34 const v8::PropertyCallbackInfo<v8::Integer>& info) {
35 CJS_Runtime* pRuntime =
Tom Sepeze99ee7f2018-02-01 20:24:43 +000036 CJS_Runtime::RuntimeFromIsolateCurrentContext(info.GetIsolate());
Dan Sinclair4b172c42017-10-23 11:22:31 -040037 if (!pRuntime)
38 return;
39
Tom Sepez57e09772018-02-05 18:52:09 +000040 CJS_Object* pJSObj = pRuntime->GetObjectPrivate(info.Holder());
Dan Sinclair4b172c42017-10-23 11:22:31 -040041 if (!pJSObj)
42 return;
43
Dan Sinclairf7435522018-02-05 22:27:22 +000044 Alt* pObj = static_cast<Alt*>(pJSObj);
Adam Klein4c451ba2018-01-17 21:06:27 +000045 CJS_Return result =
46 pObj->QueryProperty(PropFromV8Prop(info.GetIsolate(), property).c_str());
Dan Sinclair8f524d62017-10-25 13:30:31 -040047 info.GetReturnValue().Set(!result.HasError() ? 4 : 0);
Dan Sinclair4b172c42017-10-23 11:22:31 -040048}
49
50template <class Alt>
51void JSSpecialPropGet(const char* class_name,
52 v8::Local<v8::String> property,
53 const v8::PropertyCallbackInfo<v8::Value>& info) {
54 CJS_Runtime* pRuntime =
Tom Sepeze99ee7f2018-02-01 20:24:43 +000055 CJS_Runtime::RuntimeFromIsolateCurrentContext(info.GetIsolate());
Dan Sinclair4b172c42017-10-23 11:22:31 -040056 if (!pRuntime)
57 return;
58
Tom Sepez57e09772018-02-05 18:52:09 +000059 CJS_Object* pJSObj = pRuntime->GetObjectPrivate(info.Holder());
Dan Sinclair4b172c42017-10-23 11:22:31 -040060 if (!pJSObj)
61 return;
62
Dan Sinclairf7435522018-02-05 22:27:22 +000063 Alt* pObj = static_cast<Alt*>(pJSObj);
Adam Klein4c451ba2018-01-17 21:06:27 +000064 CJS_Return result = pObj->GetProperty(
65 pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str());
Dan Sinclair8f524d62017-10-25 13:30:31 -040066 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 =
Tom Sepeze99ee7f2018-02-01 20:24:43 +000082 CJS_Runtime::RuntimeFromIsolateCurrentContext(info.GetIsolate());
Dan Sinclair4b172c42017-10-23 11:22:31 -040083 if (!pRuntime)
84 return;
85
Tom Sepez57e09772018-02-05 18:52:09 +000086 CJS_Object* pJSObj = pRuntime->GetObjectPrivate(info.Holder());
Dan Sinclair4b172c42017-10-23 11:22:31 -040087 if (!pJSObj)
88 return;
89
Dan Sinclairf7435522018-02-05 22:27:22 +000090 Alt* pObj = static_cast<Alt*>(pJSObj);
Adam Klein4c451ba2018-01-17 21:06:27 +000091 CJS_Return result = pObj->SetProperty(
92 pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str(), value);
Dan Sinclair8f524d62017-10-25 13:30:31 -040093 if (result.HasError()) {
94 pRuntime->Error(
95 JSFormatErrorString(class_name, "PutProperty", result.Error()));
96 }
Dan Sinclair4b172c42017-10-23 11:22:31 -040097}
98
99template <class Alt>
100void JSSpecialPropDel(const char* class_name,
101 v8::Local<v8::String> property,
102 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
103 CJS_Runtime* pRuntime =
Tom Sepeze99ee7f2018-02-01 20:24:43 +0000104 CJS_Runtime::RuntimeFromIsolateCurrentContext(info.GetIsolate());
Dan Sinclair4b172c42017-10-23 11:22:31 -0400105 if (!pRuntime)
106 return;
107
Tom Sepez57e09772018-02-05 18:52:09 +0000108 CJS_Object* pJSObj = pRuntime->GetObjectPrivate(info.Holder());
Dan Sinclair4b172c42017-10-23 11:22:31 -0400109 if (!pJSObj)
110 return;
111
Dan Sinclairf7435522018-02-05 22:27:22 +0000112 Alt* pObj = static_cast<Alt*>(pJSObj);
Adam Klein4c451ba2018-01-17 21:06:27 +0000113 CJS_Return result = pObj->DelProperty(
114 pRuntime, PropFromV8Prop(info.GetIsolate(), property).c_str());
Dan Sinclair8f524d62017-10-25 13:30:31 -0400115 if (result.HasError()) {
116 // TODO(dsinclair): Should this set the pRuntime->Error result?
Henrique Nakashima11506302017-12-06 22:09:40 +0000117 // ByteString cbName =
118 // ByteString::Format("%s.%s", class_name, "DelProperty");
Dan Sinclair4b172c42017-10-23 11:22:31 -0400119 }
120}
121
Dan Sinclair4b172c42017-10-23 11:22:31 -0400122} // namespace
123
Dan Sinclairf7435522018-02-05 22:27:22 +0000124CJS_Global::JSGlobalData::JSGlobalData()
125 : nType(JS_GlobalDataType::NUMBER),
126 dData(0),
127 bData(false),
128 sData(""),
129 bPersistent(false),
130 bDeleted(false) {}
131
132CJS_Global::JSGlobalData::~JSGlobalData() {
133 pData.Reset();
134}
135
Dan Sinclairc94a7932017-10-26 16:48:57 -0400136const JSMethodSpec CJS_Global::MethodSpecs[] = {
Dan Sinclair909fa2d2017-12-12 01:53:28 +0000137 {"setPersistent", setPersistent_static}};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700138
Dan Sinclairef299532017-10-26 16:48:30 -0400139int CJS_Global::ObjDefnID = -1;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700140
Dan Sinclair4b172c42017-10-23 11:22:31 -0400141// static
142void CJS_Global::setPersistent_static(
143 const v8::FunctionCallbackInfo<v8::Value>& info) {
Dan Sinclairf7435522018-02-05 22:27:22 +0000144 JSMethod<CJS_Global, &CJS_Global::setPersistent>("setPersistent", "global",
145 info);
Dan Sinclair4b172c42017-10-23 11:22:31 -0400146}
147
Dan Sinclairef299532017-10-26 16:48:30 -0400148// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400149void CJS_Global::queryprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000150 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400151 const v8::PropertyCallbackInfo<v8::Integer>& info) {
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000152 DCHECK(property->IsString());
153 JSSpecialPropQuery<CJS_Global>(
154 "global",
155 v8::Local<v8::String>::New(info.GetIsolate(), property->ToString()),
156 info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400157}
158
Dan Sinclairef299532017-10-26 16:48:30 -0400159// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400160void CJS_Global::getprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000161 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400162 const v8::PropertyCallbackInfo<v8::Value>& info) {
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000163 DCHECK(property->IsString());
164 JSSpecialPropGet<CJS_Global>(
165 "global",
166 v8::Local<v8::String>::New(info.GetIsolate(), property->ToString()),
167 info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400168}
169
Dan Sinclairef299532017-10-26 16:48:30 -0400170// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400171void CJS_Global::putprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000172 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400173 v8::Local<v8::Value> value,
174 const v8::PropertyCallbackInfo<v8::Value>& info) {
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000175 DCHECK(property->IsString());
176 JSSpecialPropPut<CJS_Global>(
177 "global",
178 v8::Local<v8::String>::New(info.GetIsolate(), property->ToString()),
179 value, info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400180}
181
Dan Sinclairef299532017-10-26 16:48:30 -0400182// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400183void CJS_Global::delprop_static(
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000184 v8::Local<v8::Name> property,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400185 const v8::PropertyCallbackInfo<v8::Boolean>& info) {
Franziska Hinkelmann9a635e82018-03-21 12:58:25 +0000186 DCHECK(property->IsString());
187 JSSpecialPropDel<CJS_Global>(
188 "global",
189 v8::Local<v8::String>::New(info.GetIsolate(), property->ToString()),
190 info);
Dan Sinclair89d26c82017-10-26 12:21:28 -0400191}
192
Dan Sinclairef299532017-10-26 16:48:30 -0400193// static
Dan Sinclair89d26c82017-10-26 12:21:28 -0400194void CJS_Global::DefineAllProperties(CFXJS_Engine* pEngine) {
195 pEngine->DefineObjAllProperties(
Dan Sinclairef299532017-10-26 16:48:30 -0400196 ObjDefnID, CJS_Global::queryprop_static, CJS_Global::getprop_static,
Dan Sinclair89d26c82017-10-26 12:21:28 -0400197 CJS_Global::putprop_static, CJS_Global::delprop_static);
198}
199
Dan Sinclairef299532017-10-26 16:48:30 -0400200// static
Dan Sinclairbef4d3e2017-10-26 16:49:38 -0400201void CJS_Global::DefineJSObjects(CFXJS_Engine* pEngine) {
202 ObjDefnID = pEngine->DefineObj("global", FXJSOBJTYPE_STATIC,
Dan Sinclair998fee32018-02-05 21:43:19 +0000203 JSConstructor<CJS_Global>, JSDestructor);
Dan Sinclair909fa2d2017-12-12 01:53:28 +0000204 DefineMethods(pEngine, ObjDefnID, MethodSpecs, FX_ArraySize(MethodSpecs));
Dan Sinclair89d26c82017-10-26 12:21:28 -0400205 DefineAllProperties(pEngine);
206}
207
Tom Sepez36aae4f2018-06-04 19:44:37 +0000208CJS_Global::CJS_Global(v8::Local<v8::Object> pObject, CJS_Runtime* pRuntime)
209 : CJS_Object(pObject, pRuntime) {}
Dan Sinclair998fee32018-02-05 21:43:19 +0000210
Dan Sinclairf7435522018-02-05 22:27:22 +0000211CJS_Global::~CJS_Global() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212 DestroyGlobalPersisitentVariables();
Tom Sepezf4583622015-09-14 15:06:53 -0700213 m_pGlobalData->Release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700214}
215
Tom Sepez36aae4f2018-06-04 19:44:37 +0000216void CJS_Global::InitInstance() {
217 Initial(GetRuntime()->GetFormFillEnv());
Dan Sinclairf7435522018-02-05 22:27:22 +0000218}
219
220void CJS_Global::Initial(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
Tom Sepez77f6d0f2017-02-23 12:14:10 -0800221 m_pFormFillEnv.Reset(pFormFillEnv);
dsinclair8779fa82016-10-12 12:05:44 -0700222 m_pGlobalData = CJS_GlobalData::GetRetainedInstance(pFormFillEnv);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700223 UpdateGlobalPersistentVariables();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700224}
Tom Sepezbdeeb8a2015-05-27 12:25:00 -0700225
Dan Sinclairf7435522018-02-05 22:27:22 +0000226CJS_Return CJS_Global::QueryProperty(const wchar_t* propname) {
Dan Sinclair8f524d62017-10-25 13:30:31 -0400227 return CJS_Return(WideString(propname) != L"setPersistent");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700228}
229
Dan Sinclairf7435522018-02-05 22:27:22 +0000230CJS_Return CJS_Global::DelProperty(CJS_Runtime* pRuntime,
231 const wchar_t* propname) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400232 auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
Tom Sepeza7757232017-04-18 11:10:39 -0700233 if (it == m_MapGlobal.end())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400234 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700235
tsepez4cf55152016-11-02 14:37:54 -0700236 it->second->bDeleted = true;
Dan Sinclair8f524d62017-10-25 13:30:31 -0400237 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700238}
239
Dan Sinclairf7435522018-02-05 22:27:22 +0000240CJS_Return CJS_Global::GetProperty(CJS_Runtime* pRuntime,
241 const wchar_t* propname) {
dan sinclaircbe23db2017-10-19 14:29:33 -0400242 auto it = m_MapGlobal.find(ByteString::FromUnicode(propname));
dan sinclair5daf07a2017-10-24 21:46:57 -0400243 if (it == m_MapGlobal.end())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400244 return CJS_Return(true);
dan sinclaircbe23db2017-10-19 14:29:33 -0400245
246 JSGlobalData* pData = it->second.get();
dan sinclair5daf07a2017-10-24 21:46:57 -0400247 if (pData->bDeleted)
Dan Sinclair8f524d62017-10-25 13:30:31 -0400248 return CJS_Return(true);
dan sinclaircbe23db2017-10-19 14:29:33 -0400249
250 switch (pData->nType) {
251 case JS_GlobalDataType::NUMBER:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400252 return CJS_Return(pRuntime->NewNumber(pData->dData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400253 case JS_GlobalDataType::BOOLEAN:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400254 return CJS_Return(pRuntime->NewBoolean(pData->bData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400255 case JS_GlobalDataType::STRING:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400256 return CJS_Return(pRuntime->NewString(
Dan Sinclaire4974922017-10-24 09:36:16 -0400257 WideString::FromLocal(pData->sData.c_str()).c_str()));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400258 case JS_GlobalDataType::OBJECT:
259 return CJS_Return(
260 v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
dan sinclaircbe23db2017-10-19 14:29:33 -0400261 case JS_GlobalDataType::NULLOBJ:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400262 return CJS_Return(pRuntime->NewNull());
dan sinclaircbe23db2017-10-19 14:29:33 -0400263 default:
264 break;
265 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400266 return CJS_Return(false);
dan sinclaircbe23db2017-10-19 14:29:33 -0400267}
268
Dan Sinclairf7435522018-02-05 22:27:22 +0000269CJS_Return CJS_Global::SetProperty(CJS_Runtime* pRuntime,
270 const wchar_t* propname,
271 v8::Local<v8::Value> vp) {
dan sinclaircbe23db2017-10-19 14:29:33 -0400272 ByteString sPropName = ByteString::FromUnicode(propname);
dan sinclair80435cb2017-10-24 21:40:24 -0400273 if (vp->IsNumber()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400274 return SetGlobalVariables(sPropName, JS_GlobalDataType::NUMBER,
dan sinclair80435cb2017-10-24 21:40:24 -0400275 pRuntime->ToDouble(vp), false, "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400276 v8::Local<v8::Object>(), false);
277 }
dan sinclair80435cb2017-10-24 21:40:24 -0400278 if (vp->IsBoolean()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400279 return SetGlobalVariables(sPropName, JS_GlobalDataType::BOOLEAN, 0,
dan sinclair80435cb2017-10-24 21:40:24 -0400280 pRuntime->ToBoolean(vp), "",
Dan Sinclair3cac3602017-10-24 15:15:27 -0400281 v8::Local<v8::Object>(), false);
282 }
dan sinclair80435cb2017-10-24 21:40:24 -0400283 if (vp->IsString()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400284 return SetGlobalVariables(
285 sPropName, JS_GlobalDataType::STRING, 0, false,
dan sinclair80435cb2017-10-24 21:40:24 -0400286 ByteString::FromUnicode(pRuntime->ToWideString(vp)),
Dan Sinclair3cac3602017-10-24 15:15:27 -0400287 v8::Local<v8::Object>(), false);
288 }
dan sinclair80435cb2017-10-24 21:40:24 -0400289 if (vp->IsObject()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400290 return SetGlobalVariables(sPropName, JS_GlobalDataType::OBJECT, 0, false,
dan sinclair80435cb2017-10-24 21:40:24 -0400291 "", pRuntime->ToObject(vp), false);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400292 }
dan sinclair80435cb2017-10-24 21:40:24 -0400293 if (vp->IsNull()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400294 return SetGlobalVariables(sPropName, JS_GlobalDataType::NULLOBJ, 0, false,
295 "", v8::Local<v8::Object>(), false);
296 }
dan sinclair80435cb2017-10-24 21:40:24 -0400297 if (vp->IsUndefined()) {
Dan Sinclair3cac3602017-10-24 15:15:27 -0400298 DelProperty(pRuntime, propname);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400299 return CJS_Return(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700300 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400301 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700302}
303
Dan Sinclairf7435522018-02-05 22:27:22 +0000304CJS_Return CJS_Global::setPersistent(
dan sinclair80435cb2017-10-24 21:40:24 -0400305 CJS_Runtime* pRuntime,
Dan Sinclair8f524d62017-10-25 13:30:31 -0400306 const std::vector<v8::Local<v8::Value>>& params) {
307 if (params.size() != 2)
Dan Sinclaird6e9cfa2017-10-30 21:19:42 +0000308 return CJS_Return(JSGetStringFromID(JSMessage::kParamError));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400309
Dan Sinclair1b2a18e2017-10-24 13:56:29 -0400310 auto it = m_MapGlobal.find(
dan sinclair80435cb2017-10-24 21:40:24 -0400311 ByteString::FromUnicode(pRuntime->ToWideString(params[0])));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400312 if (it == m_MapGlobal.end() || it->second->bDeleted)
Dan Sinclaird6e9cfa2017-10-30 21:19:42 +0000313 return CJS_Return(JSGetStringFromID(JSMessage::kGlobalNotFoundError));
Dan Sinclair8f524d62017-10-25 13:30:31 -0400314
dan sinclair80435cb2017-10-24 21:40:24 -0400315 it->second->bPersistent = pRuntime->ToBoolean(params[1]);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400316 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700317}
318
Dan Sinclairf7435522018-02-05 22:27:22 +0000319void CJS_Global::UpdateGlobalPersistentVariables() {
tsepezb4694242016-08-15 16:44:55 -0700320 CJS_Runtime* pRuntime =
Tom Sepeze99ee7f2018-02-01 20:24:43 +0000321 static_cast<CJS_Runtime*>(CFXJS_Engine::EngineFromIsolateCurrentContext(
Dan Sinclairf7435522018-02-05 22:27:22 +0000322 ToV8Object()->GetIsolate()));
tsepezb4694242016-08-15 16:44:55 -0700323
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700324 for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
325 CJS_GlobalData_Element* pData = m_pGlobalData->GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700326 switch (pData->data.nType) {
weili47228ac2016-07-20 10:35:31 -0700327 case JS_GlobalDataType::NUMBER:
328 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NUMBER,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329 pData->data.dData, false, "",
330 v8::Local<v8::Object>(), pData->bPersistent == 1);
Dan Sinclairf7435522018-02-05 22:27:22 +0000331 pRuntime->PutObjectProperty(ToV8Object(), pData->data.sKey.UTF8Decode(),
tsepeze6cf0132017-01-18 14:38:18 -0800332 pRuntime->NewNumber(pData->data.dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700333 break;
weili47228ac2016-07-20 10:35:31 -0700334 case JS_GlobalDataType::BOOLEAN:
335 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::BOOLEAN, 0,
tsepeze6cf0132017-01-18 14:38:18 -0800336 pData->data.bData == 1, "", v8::Local<v8::Object>(),
337 pData->bPersistent == 1);
338 pRuntime->PutObjectProperty(
Dan Sinclairf7435522018-02-05 22:27:22 +0000339 ToV8Object(), pData->data.sKey.UTF8Decode(),
tsepeze6cf0132017-01-18 14:38:18 -0800340 pRuntime->NewBoolean(pData->data.bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700341 break;
weili47228ac2016-07-20 10:35:31 -0700342 case JS_GlobalDataType::STRING:
343 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::STRING, 0,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700344 false, pData->data.sData, v8::Local<v8::Object>(),
345 pData->bPersistent == 1);
tsepeze6cf0132017-01-18 14:38:18 -0800346 pRuntime->PutObjectProperty(
Dan Sinclairf7435522018-02-05 22:27:22 +0000347 ToV8Object(), pData->data.sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400348 pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700349 break;
weili47228ac2016-07-20 10:35:31 -0700350 case JS_GlobalDataType::OBJECT: {
Tom Sepez9ad9a5f2018-02-07 21:07:24 +0000351 v8::Local<v8::Object> pObj = pRuntime->NewObject();
Tom Sepez63b2fc72017-08-14 16:24:29 -0700352 if (!pObj.IsEmpty()) {
353 PutObjectProperty(pObj, &pData->data);
354 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::OBJECT, 0,
355 false, "", pObj, pData->bPersistent == 1);
Dan Sinclairf7435522018-02-05 22:27:22 +0000356 pRuntime->PutObjectProperty(ToV8Object(),
Tom Sepez63b2fc72017-08-14 16:24:29 -0700357 pData->data.sKey.UTF8Decode(), pObj);
358 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700359 } break;
weili47228ac2016-07-20 10:35:31 -0700360 case JS_GlobalDataType::NULLOBJ:
361 SetGlobalVariables(pData->data.sKey, JS_GlobalDataType::NULLOBJ, 0,
362 false, "", v8::Local<v8::Object>(),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363 pData->bPersistent == 1);
Dan Sinclairf7435522018-02-05 22:27:22 +0000364 pRuntime->PutObjectProperty(ToV8Object(), pData->data.sKey.UTF8Decode(),
tsepeze6cf0132017-01-18 14:38:18 -0800365 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700366 break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700367 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700368 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700369}
370
Dan Sinclairf7435522018-02-05 22:27:22 +0000371void CJS_Global::CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime) {
Tom Sepeza7757232017-04-18 11:10:39 -0700372 for (const auto& iter : m_MapGlobal) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400373 ByteString name = iter.first;
Tom Sepeza7757232017-04-18 11:10:39 -0700374 JSGlobalData* pData = iter.second.get();
Tom Sepez09d33bc2015-08-19 09:49:24 -0700375 if (pData->bDeleted) {
376 m_pGlobalData->DeleteGlobalVariable(name);
Tom Sepeza7757232017-04-18 11:10:39 -0700377 continue;
378 }
379 switch (pData->nType) {
380 case JS_GlobalDataType::NUMBER:
381 m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
382 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
383 break;
384 case JS_GlobalDataType::BOOLEAN:
385 m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
386 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
387 break;
388 case JS_GlobalDataType::STRING:
389 m_pGlobalData->SetGlobalVariableString(name, pData->sData);
390 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
391 break;
392 case JS_GlobalDataType::OBJECT: {
393 CJS_GlobalVariableArray array;
Dan Sinclairf7435522018-02-05 22:27:22 +0000394 v8::Local<v8::Object> obj =
395 v8::Local<v8::Object>::New(GetIsolate(), pData->pData);
Tom Sepeza7757232017-04-18 11:10:39 -0700396 ObjectToArray(pRuntime, obj, array);
397 m_pGlobalData->SetGlobalVariableObject(name, array);
398 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
399 } break;
400 case JS_GlobalDataType::NULLOBJ:
401 m_pGlobalData->SetGlobalVariableNull(name);
402 m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
403 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700404 }
405 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700406}
407
Dan Sinclairf7435522018-02-05 22:27:22 +0000408void CJS_Global::ObjectToArray(CJS_Runtime* pRuntime,
409 v8::Local<v8::Object> pObj,
410 CJS_GlobalVariableArray& array) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400411 std::vector<WideString> pKeyList = pRuntime->GetObjectPropertyNames(pObj);
tsepezd0b6ed12016-08-11 19:50:57 -0700412 for (const auto& ws : pKeyList) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400413 ByteString sKey = ws.UTF8Encode();
tsepezb4694242016-08-15 16:44:55 -0700414 v8::Local<v8::Value> v = pRuntime->GetObjectProperty(pObj, ws);
Dan Sinclair3cac3602017-10-24 15:15:27 -0400415 if (v->IsNumber()) {
416 CJS_KeyValue* pObjElement = new CJS_KeyValue;
417 pObjElement->nType = JS_GlobalDataType::NUMBER;
418 pObjElement->sKey = sKey;
419 pObjElement->dData = pRuntime->ToDouble(v);
420 array.Add(pObjElement);
421 continue;
422 }
423 if (v->IsBoolean()) {
424 CJS_KeyValue* pObjElement = new CJS_KeyValue;
425 pObjElement->nType = JS_GlobalDataType::BOOLEAN;
426 pObjElement->sKey = sKey;
427 pObjElement->dData = pRuntime->ToBoolean(v);
428 array.Add(pObjElement);
429 continue;
430 }
431 if (v->IsString()) {
432 ByteString sValue = ByteString::FromUnicode(pRuntime->ToWideString(v));
433 CJS_KeyValue* pObjElement = new CJS_KeyValue;
434 pObjElement->nType = JS_GlobalDataType::STRING;
435 pObjElement->sKey = sKey;
436 pObjElement->sData = sValue;
437 array.Add(pObjElement);
438 continue;
439 }
440 if (v->IsObject()) {
441 CJS_KeyValue* pObjElement = new CJS_KeyValue;
442 pObjElement->nType = JS_GlobalDataType::OBJECT;
443 pObjElement->sKey = sKey;
444 ObjectToArray(pRuntime, pRuntime->ToObject(v), pObjElement->objData);
445 array.Add(pObjElement);
446 continue;
447 }
448 if (v->IsNull()) {
449 CJS_KeyValue* pObjElement = new CJS_KeyValue;
450 pObjElement->nType = JS_GlobalDataType::NULLOBJ;
451 pObjElement->sKey = sKey;
452 array.Add(pObjElement);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700453 }
454 }
455}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700456
Dan Sinclairf7435522018-02-05 22:27:22 +0000457void CJS_Global::PutObjectProperty(v8::Local<v8::Object> pObj,
458 CJS_KeyValue* pData) {
459 CJS_Runtime* pRuntime =
460 CJS_Runtime::RuntimeFromIsolateCurrentContext(ToV8Object()->GetIsolate());
tsepezb4694242016-08-15 16:44:55 -0700461
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700462 for (int i = 0, sz = pData->objData.Count(); i < sz; i++) {
463 CJS_KeyValue* pObjData = pData->objData.GetAt(i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700464 switch (pObjData->nType) {
weili47228ac2016-07-20 10:35:31 -0700465 case JS_GlobalDataType::NUMBER:
tsepeze6cf0132017-01-18 14:38:18 -0800466 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
467 pRuntime->NewNumber(pObjData->dData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468 break;
weili47228ac2016-07-20 10:35:31 -0700469 case JS_GlobalDataType::BOOLEAN:
tsepeze6cf0132017-01-18 14:38:18 -0800470 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
471 pRuntime->NewBoolean(pObjData->bData == 1));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700472 break;
weili47228ac2016-07-20 10:35:31 -0700473 case JS_GlobalDataType::STRING:
tsepeze6cf0132017-01-18 14:38:18 -0800474 pRuntime->PutObjectProperty(
475 pObj, pObjData->sKey.UTF8Decode(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400476 pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringView()));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700477 break;
weili47228ac2016-07-20 10:35:31 -0700478 case JS_GlobalDataType::OBJECT: {
Tom Sepez9ad9a5f2018-02-07 21:07:24 +0000479 v8::Local<v8::Object> pNewObj = pRuntime->NewObject();
Tom Sepez63b2fc72017-08-14 16:24:29 -0700480 if (!pNewObj.IsEmpty()) {
481 PutObjectProperty(pNewObj, pObjData);
482 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
483 pNewObj);
484 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 } break;
weili47228ac2016-07-20 10:35:31 -0700486 case JS_GlobalDataType::NULLOBJ:
tsepeze6cf0132017-01-18 14:38:18 -0800487 pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
488 pRuntime->NewNull());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700489 break;
490 }
491 }
492}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700493
Dan Sinclairf7435522018-02-05 22:27:22 +0000494void CJS_Global::DestroyGlobalPersisitentVariables() {
Tom Sepeza7757232017-04-18 11:10:39 -0700495 m_MapGlobal.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700496}
497
Dan Sinclairf7435522018-02-05 22:27:22 +0000498CJS_Return CJS_Global::SetGlobalVariables(const ByteString& propname,
499 JS_GlobalDataType nType,
500 double dData,
501 bool bData,
502 const ByteString& sData,
503 v8::Local<v8::Object> pData,
504 bool bDefaultPersistent) {
tsepezb4c9f3f2016-04-13 15:41:21 -0700505 if (propname.IsEmpty())
Dan Sinclair8f524d62017-10-25 13:30:31 -0400506 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700507
Tom Sepeza7757232017-04-18 11:10:39 -0700508 auto it = m_MapGlobal.find(propname);
509 if (it != m_MapGlobal.end()) {
510 JSGlobalData* pTemp = it->second.get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700511 if (pTemp->bDeleted || pTemp->nType != nType) {
512 pTemp->dData = 0;
513 pTemp->bData = 0;
Lei Zhangfe2cd4d2017-11-22 20:04:12 +0000514 pTemp->sData.clear();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700515 pTemp->nType = nType;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700516 }
tsepez4cf55152016-11-02 14:37:54 -0700517 pTemp->bDeleted = false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700518 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700519 case JS_GlobalDataType::NUMBER:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700520 pTemp->dData = dData;
Tom Sepeza7757232017-04-18 11:10:39 -0700521 break;
522 case JS_GlobalDataType::BOOLEAN:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700523 pTemp->bData = bData;
Tom Sepeza7757232017-04-18 11:10:39 -0700524 break;
525 case JS_GlobalDataType::STRING:
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700526 pTemp->sData = sData;
Tom Sepeza7757232017-04-18 11:10:39 -0700527 break;
528 case JS_GlobalDataType::OBJECT:
Tom Sepez371379d2015-11-06 08:29:39 -0800529 pTemp->pData.Reset(pData->GetIsolate(), pData);
Tom Sepeza7757232017-04-18 11:10:39 -0700530 break;
weili47228ac2016-07-20 10:35:31 -0700531 case JS_GlobalDataType::NULLOBJ:
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700532 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700533 default:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400534 return CJS_Return(false);
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700535 }
Dan Sinclair8f524d62017-10-25 13:30:31 -0400536 return CJS_Return(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700537 }
538
Tom Sepeza7757232017-04-18 11:10:39 -0700539 auto pNewData = pdfium::MakeUnique<JSGlobalData>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700540 switch (nType) {
Tom Sepeza7757232017-04-18 11:10:39 -0700541 case JS_GlobalDataType::NUMBER:
weili47228ac2016-07-20 10:35:31 -0700542 pNewData->nType = JS_GlobalDataType::NUMBER;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700543 pNewData->dData = dData;
544 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700545 break;
546 case JS_GlobalDataType::BOOLEAN:
weili47228ac2016-07-20 10:35:31 -0700547 pNewData->nType = JS_GlobalDataType::BOOLEAN;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700548 pNewData->bData = bData;
549 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700550 break;
551 case JS_GlobalDataType::STRING:
weili47228ac2016-07-20 10:35:31 -0700552 pNewData->nType = JS_GlobalDataType::STRING;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700553 pNewData->sData = sData;
554 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700555 break;
556 case JS_GlobalDataType::OBJECT:
weili47228ac2016-07-20 10:35:31 -0700557 pNewData->nType = JS_GlobalDataType::OBJECT;
Tom Sepez371379d2015-11-06 08:29:39 -0800558 pNewData->pData.Reset(pData->GetIsolate(), pData);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700560 break;
561 case JS_GlobalDataType::NULLOBJ:
weili47228ac2016-07-20 10:35:31 -0700562 pNewData->nType = JS_GlobalDataType::NULLOBJ;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700563 pNewData->bPersistent = bDefaultPersistent;
Tom Sepeza7757232017-04-18 11:10:39 -0700564 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700565 default:
Dan Sinclair8f524d62017-10-25 13:30:31 -0400566 return CJS_Return(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700567 }
Tom Sepeza7757232017-04-18 11:10:39 -0700568 m_MapGlobal[propname] = std::move(pNewData);
Dan Sinclair8f524d62017-10-25 13:30:31 -0400569 return CJS_Return(true);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700570}