blob: 4c6398870dfb1e2c16248b26c5d8fc358cb02e9f [file] [log] [blame]
John Abd-El-Malek5110c472014-05-17 22:33:34 -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-Malek5110c472014-05-17 22:33:34 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
dsinclair43554682016-09-29 17:29:48 -07007#include "fxjs/fxjs_v8.h"
John Abd-El-Malek5110c472014-05-17 22:33:34 -07008
Dan Sinclair3ebd1212016-03-09 09:59:23 -05009#include <vector>
10
Chris Palmere4b035b2017-03-26 15:48:34 -070011#include "third_party/base/allocator/partition_allocator/partition_alloc.h"
Lei Zhang4d4a4422015-10-08 12:00:14 -070012
Tom Sepezbd7fabf2015-09-28 10:31:27 -070013// Keep this consistent with the values defined in gin/public/context_holder.h
14// (without actually requiring a dependency on gin itself for the standalone
15// embedders of PDFIum). The value we want to use is:
16// kPerContextDataStartIndex + kEmbedderPDFium, which is 3.
17static const unsigned int kPerContextDataIndex = 3u;
Tom Sepeza72e8e22015-10-07 10:17:53 -070018static unsigned int g_embedderDataSlot = 1u;
19static v8::Isolate* g_isolate = nullptr;
Lei Zhang4d4a4422015-10-08 12:00:14 -070020static size_t g_isolate_ref_count = 0;
Tom Sepeza72e8e22015-10-07 10:17:53 -070021static FXJS_ArrayBufferAllocator* g_arrayBufferAllocator = nullptr;
Tom Sepez8b315b62015-10-02 08:59:57 -070022static v8::Global<v8::ObjectTemplate>* g_DefaultGlobalObjectTemplate = nullptr;
Tom Sepez3f72fb42017-02-27 11:43:55 -080023static wchar_t kPerObjectDataTag[] = L"CFXJS_PerObjectData";
Tom Sepez016a3472015-09-30 15:50:57 -070024
Tom Sepez6cf117c2015-11-06 14:52:10 -080025class CFXJS_PerObjectData {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070026 public:
Lei Zhangd88a3642015-11-10 09:38:57 -080027 explicit CFXJS_PerObjectData(int nObjDefID)
Tom Sepez6cf117c2015-11-06 14:52:10 -080028 : m_ObjDefID(nObjDefID), m_pPrivate(nullptr) {}
Tom Sepezed7b2b52015-09-22 08:36:17 -070029
Tom Sepez3f72fb42017-02-27 11:43:55 -080030 static void SetInObject(CFXJS_PerObjectData* pData,
31 v8::Local<v8::Object> pObj) {
32 if (pObj->InternalFieldCount() == 2) {
33 pObj->SetAlignedPointerInInternalField(0, pData);
34 pObj->SetAlignedPointerInInternalField(
35 1, static_cast<void*>(kPerObjectDataTag));
36 }
37 }
38
39 static CFXJS_PerObjectData* GetFromObject(v8::Local<v8::Object> pObj) {
40 if (pObj.IsEmpty() || pObj->InternalFieldCount() != 2 ||
41 pObj->GetAlignedPointerFromInternalField(1) !=
42 static_cast<void*>(kPerObjectDataTag)) {
43 return nullptr;
44 }
45 return static_cast<CFXJS_PerObjectData*>(
46 pObj->GetAlignedPointerFromInternalField(0));
47 }
48
Lei Zhangd88a3642015-11-10 09:38:57 -080049 const int m_ObjDefID;
Tom Sepez6cf117c2015-11-06 14:52:10 -080050 void* m_pPrivate;
John Abd-El-Malek5110c472014-05-17 22:33:34 -070051};
52
Tom Sepezed7b2b52015-09-22 08:36:17 -070053class CFXJS_ObjDefinition {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070054 public:
Tom Sepezed7b2b52015-09-22 08:36:17 -070055 static int MaxID(v8::Isolate* pIsolate) {
Lei Zhangd88a3642015-11-10 09:38:57 -080056 return FXJS_PerIsolateData::Get(pIsolate)->m_ObjectDefnArray.size();
Tom Sepezed7b2b52015-09-22 08:36:17 -070057 }
Lei Zhangd88a3642015-11-10 09:38:57 -080058
Tom Sepezed7b2b52015-09-22 08:36:17 -070059 static CFXJS_ObjDefinition* ForID(v8::Isolate* pIsolate, int id) {
60 // Note: GetAt() halts if out-of-range even in release builds.
weilia4ad5952016-09-22 10:38:53 -070061 return FXJS_PerIsolateData::Get(pIsolate)->m_ObjectDefnArray[id].get();
Tom Sepezed7b2b52015-09-22 08:36:17 -070062 }
Lei Zhangd88a3642015-11-10 09:38:57 -080063
Tom Sepezed7b2b52015-09-22 08:36:17 -070064 CFXJS_ObjDefinition(v8::Isolate* isolate,
Tom Sepez892d7512017-02-21 13:57:13 -080065 const char* sObjName,
Tom Sepezed7b2b52015-09-22 08:36:17 -070066 FXJSOBJTYPE eObjType,
tsepezb4694242016-08-15 16:44:55 -070067 CFXJS_Engine::Constructor pConstructor,
68 CFXJS_Engine::Destructor pDestructor)
Tom Sepezcd56a7d2015-10-06 11:45:28 -070069 : m_ObjName(sObjName),
70 m_ObjType(eObjType),
Nico Weber9d8ec5a2015-08-04 13:00:21 -070071 m_pConstructor(pConstructor),
72 m_pDestructor(pDestructor),
Tom Sepez016a3472015-09-30 15:50:57 -070073 m_pIsolate(isolate) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070074 v8::Isolate::Scope isolate_scope(isolate);
75 v8::HandleScope handle_scope(isolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -070076
Tom Sepez016a3472015-09-30 15:50:57 -070077 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
78 fun->InstanceTemplate()->SetInternalFieldCount(2);
Tom Sepezc5a14722017-02-24 15:31:12 -080079 fun->SetCallHandler([](const v8::FunctionCallbackInfo<v8::Value>& info) {
80 v8::Local<v8::Object> holder = info.Holder();
81 ASSERT(holder->InternalFieldCount() == 2);
82 holder->SetAlignedPointerInInternalField(0, nullptr);
83 holder->SetAlignedPointerInInternalField(1, nullptr);
84 });
jochen7e6a8482016-07-06 11:02:27 -070085 if (eObjType == FXJSOBJTYPE_GLOBAL) {
86 fun->InstanceTemplate()->Set(
87 v8::Symbol::GetToStringTag(isolate),
88 v8::String::NewFromUtf8(isolate, "global", v8::NewStringType::kNormal)
89 .ToLocalChecked());
90 }
Tom Sepez016a3472015-09-30 15:50:57 -070091 m_FunctionTemplate.Reset(isolate, fun);
92
93 v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
94 m_Signature.Reset(isolate, sig);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070095 }
Tom Sepez016a3472015-09-30 15:50:57 -070096
97 int AssignID() {
98 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_pIsolate);
weilia4ad5952016-09-22 10:38:53 -070099 pData->m_ObjectDefnArray.emplace_back(this);
Lei Zhangd88a3642015-11-10 09:38:57 -0800100 return pData->m_ObjectDefnArray.size() - 1;
Tom Sepez016a3472015-09-30 15:50:57 -0700101 }
102
103 v8::Local<v8::ObjectTemplate> GetInstanceTemplate() {
104 v8::EscapableHandleScope scope(m_pIsolate);
105 v8::Local<v8::FunctionTemplate> function =
106 m_FunctionTemplate.Get(m_pIsolate);
107 return scope.Escape(function->InstanceTemplate());
108 }
109
110 v8::Local<v8::Signature> GetSignature() {
111 v8::EscapableHandleScope scope(m_pIsolate);
112 return scope.Escape(m_Signature.Get(m_pIsolate));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700113 }
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700114
Tom Sepez892d7512017-02-21 13:57:13 -0800115 const char* const m_ObjName;
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700116 const FXJSOBJTYPE m_ObjType;
tsepezb4694242016-08-15 16:44:55 -0700117 const CFXJS_Engine::Constructor m_pConstructor;
118 const CFXJS_Engine::Destructor m_pDestructor;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700119
Tom Sepez016a3472015-09-30 15:50:57 -0700120 v8::Isolate* m_pIsolate;
121 v8::Global<v8::FunctionTemplate> m_FunctionTemplate;
122 v8::Global<v8::Signature> m_Signature;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700123};
124
Tom Sepez016a3472015-09-30 15:50:57 -0700125static v8::Local<v8::ObjectTemplate> GetGlobalObjectTemplate(
126 v8::Isolate* pIsolate) {
127 int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
128 for (int i = 0; i < maxID; ++i) {
129 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700130 if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL)
Tom Sepez016a3472015-09-30 15:50:57 -0700131 return pObjDef->GetInstanceTemplate();
132 }
Tom Sepez8b315b62015-10-02 08:59:57 -0700133 if (!g_DefaultGlobalObjectTemplate) {
jochen7e6a8482016-07-06 11:02:27 -0700134 v8::Local<v8::ObjectTemplate> hGlobalTemplate =
135 v8::ObjectTemplate::New(pIsolate);
136 hGlobalTemplate->Set(
137 v8::Symbol::GetToStringTag(pIsolate),
138 v8::String::NewFromUtf8(pIsolate, "global", v8::NewStringType::kNormal)
139 .ToLocalChecked());
140 g_DefaultGlobalObjectTemplate =
141 new v8::Global<v8::ObjectTemplate>(pIsolate, hGlobalTemplate);
Tom Sepez8b315b62015-10-02 08:59:57 -0700142 }
143 return g_DefaultGlobalObjectTemplate->Get(pIsolate);
Tom Sepez016a3472015-09-30 15:50:57 -0700144}
145
Tom Sepez39bfe122015-09-17 15:25:23 -0700146void* FXJS_ArrayBufferAllocator::Allocate(size_t length) {
Chris Palmere4b035b2017-03-26 15:48:34 -0700147 if (length > kMaxAllowedBytes)
148 return nullptr;
149 void* p = AllocateUninitialized(length);
150 if (p)
151 memset(p, 0, length);
152 return p;
Tom Sepez7d0fcbf2015-09-15 15:30:34 -0700153}
154
Tom Sepez39bfe122015-09-17 15:25:23 -0700155void* FXJS_ArrayBufferAllocator::AllocateUninitialized(size_t length) {
Chris Palmere4b035b2017-03-26 15:48:34 -0700156 if (length > kMaxAllowedBytes)
157 return nullptr;
158 return pdfium::base::PartitionAllocGeneric(
159 gArrayBufferPartitionAllocator.root(), length, "FXJS_ArrayBuffer");
Tom Sepez7d0fcbf2015-09-15 15:30:34 -0700160}
161
Tom Sepez39bfe122015-09-17 15:25:23 -0700162void FXJS_ArrayBufferAllocator::Free(void* data, size_t length) {
Chris Palmer5ff8c882017-03-31 16:09:54 -0700163 pdfium::base::PartitionFreeGeneric(gArrayBufferPartitionAllocator.root(),
164 data);
Tom Sepez7d0fcbf2015-09-15 15:30:34 -0700165}
166
jinming_wang61dc96f2016-01-28 14:39:56 +0800167void V8TemplateMapTraits::Dispose(v8::Isolate* isolate,
168 v8::Global<v8::Object> value,
169 void* key) {
170 v8::Local<v8::Object> obj = value.Get(isolate);
171 if (obj.IsEmpty())
172 return;
Tom Sepezce84f712017-05-30 17:17:33 -0700173 int id = CFXJS_Engine::GetObjDefnID(obj);
jinming_wang61dc96f2016-01-28 14:39:56 +0800174 if (id == -1)
175 return;
jinming_wang61dc96f2016-01-28 14:39:56 +0800176 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(isolate, id);
177 if (!pObjDef)
178 return;
Tom Sepezce84f712017-05-30 17:17:33 -0700179 if (pObjDef->m_pDestructor) {
180 pObjDef->m_pDestructor(CFXJS_Engine::CurrentEngineFromIsolate(isolate),
181 obj);
182 }
tsepezb4694242016-08-15 16:44:55 -0700183 CFXJS_Engine::FreeObjectPrivate(obj);
jinming_wang61dc96f2016-01-28 14:39:56 +0800184}
185
186V8TemplateMapTraits::MapType* V8TemplateMapTraits::MapFromWeakCallbackInfo(
187 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
188 V8TemplateMap* pMap =
weilia4ad5952016-09-22 10:38:53 -0700189 (FXJS_PerIsolateData::Get(data.GetIsolate()))->m_pDynamicObjsMap.get();
jinming_wang61dc96f2016-01-28 14:39:56 +0800190 return pMap ? &pMap->m_map : nullptr;
191}
192
Tom Sepeza72e8e22015-10-07 10:17:53 -0700193void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate) {
Lei Zhang4d4a4422015-10-08 12:00:14 -0700194 if (g_isolate) {
195 ASSERT(g_embedderDataSlot == embedderDataSlot);
196 ASSERT(g_isolate == pIsolate);
197 return;
198 }
Tom Sepeza72e8e22015-10-07 10:17:53 -0700199 g_embedderDataSlot = embedderDataSlot;
200 g_isolate = pIsolate;
201}
202
203void FXJS_Release() {
Lei Zhang4d4a4422015-10-08 12:00:14 -0700204 ASSERT(!g_isolate || g_isolate_ref_count == 0);
Lei Zhangb3914932015-10-08 12:08:47 -0700205 delete g_DefaultGlobalObjectTemplate;
Tom Sepeza72e8e22015-10-07 10:17:53 -0700206 g_DefaultGlobalObjectTemplate = nullptr;
207 g_isolate = nullptr;
208
209 delete g_arrayBufferAllocator;
210 g_arrayBufferAllocator = nullptr;
211}
212
213bool FXJS_GetIsolate(v8::Isolate** pResultIsolate) {
214 if (g_isolate) {
215 *pResultIsolate = g_isolate;
216 return false;
217 }
218 // Provide backwards compatibility when no external isolate.
219 if (!g_arrayBufferAllocator)
220 g_arrayBufferAllocator = new FXJS_ArrayBufferAllocator();
221 v8::Isolate::CreateParams params;
222 params.array_buffer_allocator = g_arrayBufferAllocator;
223 *pResultIsolate = v8::Isolate::New(params);
224 return true;
225}
226
Lei Zhang3fa115b2015-10-08 12:04:47 -0700227size_t FXJS_GlobalIsolateRefCount() {
228 return g_isolate_ref_count;
229}
230
weili625ad662016-06-15 11:21:33 -0700231V8TemplateMap::V8TemplateMap(v8::Isolate* isolate) : m_map(isolate) {}
232
233V8TemplateMap::~V8TemplateMap() {}
234
235void V8TemplateMap::set(void* key, v8::Local<v8::Object> handle) {
236 ASSERT(!m_map.Contains(key));
237 m_map.Set(key, handle);
238}
239
240FXJS_PerIsolateData::~FXJS_PerIsolateData() {}
241
Tom Sepezed7b2b52015-09-22 08:36:17 -0700242// static
243void FXJS_PerIsolateData::SetUp(v8::Isolate* pIsolate) {
Tom Sepez7d0fcbf2015-09-15 15:30:34 -0700244 if (!pIsolate->GetData(g_embedderDataSlot))
weilia4ad5952016-09-22 10:38:53 -0700245 pIsolate->SetData(g_embedderDataSlot, new FXJS_PerIsolateData(pIsolate));
Tom Sepezed7b2b52015-09-22 08:36:17 -0700246}
247
248// static
249FXJS_PerIsolateData* FXJS_PerIsolateData::Get(v8::Isolate* pIsolate) {
250 return static_cast<FXJS_PerIsolateData*>(
251 pIsolate->GetData(g_embedderDataSlot));
Tom Sepez7d0fcbf2015-09-15 15:30:34 -0700252}
253
weilia4ad5952016-09-22 10:38:53 -0700254FXJS_PerIsolateData::FXJS_PerIsolateData(v8::Isolate* pIsolate)
255 : m_pDynamicObjsMap(new V8TemplateMap(pIsolate)) {}
weili625ad662016-06-15 11:21:33 -0700256
tsepeza4941912016-08-15 11:40:12 -0700257CFXJS_Engine::CFXJS_Engine() : m_isolate(nullptr) {}
tsepeza4941912016-08-15 11:40:12 -0700258
weili0b2a9872016-09-21 11:50:43 -0700259CFXJS_Engine::CFXJS_Engine(v8::Isolate* pIsolate) : m_isolate(pIsolate) {}
260
tsepezb4694242016-08-15 16:44:55 -0700261CFXJS_Engine::~CFXJS_Engine() {
262 m_V8PersistentContext.Reset();
263}
Tom Sepez7d0fcbf2015-09-15 15:30:34 -0700264
tsepezb4694242016-08-15 16:44:55 -0700265// static
266CFXJS_Engine* CFXJS_Engine::CurrentEngineFromIsolate(v8::Isolate* pIsolate) {
267 return static_cast<CFXJS_Engine*>(
268 pIsolate->GetCurrentContext()->GetAlignedPointerFromEmbedderData(
269 kPerContextDataIndex));
270}
271
tsepezb4694242016-08-15 16:44:55 -0700272// static
273int CFXJS_Engine::GetObjDefnID(v8::Local<v8::Object> pObj) {
Tom Sepez3f72fb42017-02-27 11:43:55 -0800274 CFXJS_PerObjectData* pData = CFXJS_PerObjectData::GetFromObject(pObj);
275 return pData ? pData->m_ObjDefID : -1;
tsepezb4694242016-08-15 16:44:55 -0700276}
277
278// static
279void CFXJS_Engine::FreeObjectPrivate(void* pPerObjectData) {
280 delete static_cast<CFXJS_PerObjectData*>(pPerObjectData);
281}
282
283// static
284void CFXJS_Engine::FreeObjectPrivate(v8::Local<v8::Object> pObj) {
Tom Sepez3f72fb42017-02-27 11:43:55 -0800285 CFXJS_PerObjectData* pData = CFXJS_PerObjectData::GetFromObject(pObj);
tsepezb4694242016-08-15 16:44:55 -0700286 pObj->SetAlignedPointerInInternalField(0, nullptr);
Tom Sepez3f72fb42017-02-27 11:43:55 -0800287 pObj->SetAlignedPointerInInternalField(1, nullptr);
288 delete pData;
tsepezb4694242016-08-15 16:44:55 -0700289}
290
Tom Sepez892d7512017-02-21 13:57:13 -0800291int CFXJS_Engine::DefineObj(const char* sObjName,
tsepezb4694242016-08-15 16:44:55 -0700292 FXJSOBJTYPE eObjType,
293 CFXJS_Engine::Constructor pConstructor,
294 CFXJS_Engine::Destructor pDestructor) {
295 v8::Isolate::Scope isolate_scope(m_isolate);
296 v8::HandleScope handle_scope(m_isolate);
297 FXJS_PerIsolateData::SetUp(m_isolate);
Tom Sepez016a3472015-09-30 15:50:57 -0700298 CFXJS_ObjDefinition* pObjDef = new CFXJS_ObjDefinition(
tsepezb4694242016-08-15 16:44:55 -0700299 m_isolate, sObjName, eObjType, pConstructor, pDestructor);
Tom Sepez016a3472015-09-30 15:50:57 -0700300 return pObjDef->AssignID();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700301}
302
tsepezb4694242016-08-15 16:44:55 -0700303void CFXJS_Engine::DefineObjMethod(int nObjDefnID,
Tom Sepez9b99b632017-02-21 15:05:57 -0800304 const char* sMethodName,
tsepezb4694242016-08-15 16:44:55 -0700305 v8::FunctionCallback pMethodCall) {
306 v8::Isolate::Scope isolate_scope(m_isolate);
307 v8::HandleScope handle_scope(m_isolate);
Tom Sepezed7b2b52015-09-22 08:36:17 -0700308 CFXJS_ObjDefinition* pObjDef =
tsepezb4694242016-08-15 16:44:55 -0700309 CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID);
jochenc4dedf32016-07-06 05:26:23 -0700310 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(
tsepezb4694242016-08-15 16:44:55 -0700311 m_isolate, pMethodCall, v8::Local<v8::Value>(), pObjDef->GetSignature());
jochenc4dedf32016-07-06 05:26:23 -0700312 fun->RemovePrototype();
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700313 pObjDef->GetInstanceTemplate()->Set(NewString(sMethodName), fun,
314 v8::ReadOnly);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700315}
316
tsepezb4694242016-08-15 16:44:55 -0700317void CFXJS_Engine::DefineObjProperty(int nObjDefnID,
Tom Sepez4d5b8c52017-02-21 15:17:07 -0800318 const char* sPropName,
tsepezb4694242016-08-15 16:44:55 -0700319 v8::AccessorGetterCallback pPropGet,
320 v8::AccessorSetterCallback pPropPut) {
321 v8::Isolate::Scope isolate_scope(m_isolate);
322 v8::HandleScope handle_scope(m_isolate);
Tom Sepezed7b2b52015-09-22 08:36:17 -0700323 CFXJS_ObjDefinition* pObjDef =
tsepezb4694242016-08-15 16:44:55 -0700324 CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID);
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700325 pObjDef->GetInstanceTemplate()->SetAccessor(NewString(sPropName), pPropGet,
326 pPropPut);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700327}
328
tsepezb4694242016-08-15 16:44:55 -0700329void CFXJS_Engine::DefineObjAllProperties(
330 int nObjDefnID,
331 v8::NamedPropertyQueryCallback pPropQurey,
332 v8::NamedPropertyGetterCallback pPropGet,
333 v8::NamedPropertySetterCallback pPropPut,
334 v8::NamedPropertyDeleterCallback pPropDel) {
335 v8::Isolate::Scope isolate_scope(m_isolate);
336 v8::HandleScope handle_scope(m_isolate);
Tom Sepezed7b2b52015-09-22 08:36:17 -0700337 CFXJS_ObjDefinition* pObjDef =
tsepezb4694242016-08-15 16:44:55 -0700338 CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID);
Tom Sepez016a3472015-09-30 15:50:57 -0700339 pObjDef->GetInstanceTemplate()->SetNamedPropertyHandler(pPropGet, pPropPut,
340 pPropQurey, pPropDel);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700341}
342
tsepezb4694242016-08-15 16:44:55 -0700343void CFXJS_Engine::DefineObjConst(int nObjDefnID,
Tom Sepez55db0912017-02-21 15:26:52 -0800344 const char* sConstName,
tsepezb4694242016-08-15 16:44:55 -0700345 v8::Local<v8::Value> pDefault) {
346 v8::Isolate::Scope isolate_scope(m_isolate);
347 v8::HandleScope handle_scope(m_isolate);
Tom Sepezed7b2b52015-09-22 08:36:17 -0700348 CFXJS_ObjDefinition* pObjDef =
tsepezb4694242016-08-15 16:44:55 -0700349 CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID);
Tom Sepez55db0912017-02-21 15:26:52 -0800350 pObjDef->GetInstanceTemplate()->Set(m_isolate, sConstName, pDefault);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700351}
352
Tom Sepez9b99b632017-02-21 15:05:57 -0800353void CFXJS_Engine::DefineGlobalMethod(const char* sMethodName,
tsepezb4694242016-08-15 16:44:55 -0700354 v8::FunctionCallback pMethodCall) {
355 v8::Isolate::Scope isolate_scope(m_isolate);
356 v8::HandleScope handle_scope(m_isolate);
jochenc4dedf32016-07-06 05:26:23 -0700357 v8::Local<v8::FunctionTemplate> fun =
tsepezb4694242016-08-15 16:44:55 -0700358 v8::FunctionTemplate::New(m_isolate, pMethodCall);
jochenc4dedf32016-07-06 05:26:23 -0700359 fun->RemovePrototype();
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700360 GetGlobalObjectTemplate(m_isolate)->Set(NewString(sMethodName), fun,
361 v8::ReadOnly);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700362}
363
tsepezb4694242016-08-15 16:44:55 -0700364void CFXJS_Engine::DefineGlobalConst(const wchar_t* sConstName,
365 v8::FunctionCallback pConstGetter) {
366 v8::Isolate::Scope isolate_scope(m_isolate);
367 v8::HandleScope handle_scope(m_isolate);
jochenc4dedf32016-07-06 05:26:23 -0700368 v8::Local<v8::FunctionTemplate> fun =
tsepezb4694242016-08-15 16:44:55 -0700369 v8::FunctionTemplate::New(m_isolate, pConstGetter);
jochenc4dedf32016-07-06 05:26:23 -0700370 fun->RemovePrototype();
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700371 GetGlobalObjectTemplate(m_isolate)->SetAccessorProperty(NewString(sConstName),
372 fun);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700373}
374
tsepezb4694242016-08-15 16:44:55 -0700375void CFXJS_Engine::InitializeEngine() {
376 if (m_isolate == g_isolate)
Lei Zhang4d4a4422015-10-08 12:00:14 -0700377 ++g_isolate_ref_count;
378
tsepezb4694242016-08-15 16:44:55 -0700379 v8::Isolate::Scope isolate_scope(m_isolate);
380 v8::HandleScope handle_scope(m_isolate);
dsinclair7d554c92016-06-20 06:06:31 -0700381
382 // This has to happen before we call GetGlobalObjectTemplate because that
tsepezb4694242016-08-15 16:44:55 -0700383 // method gets the PerIsolateData from m_isolate.
384 FXJS_PerIsolateData::SetUp(m_isolate);
dsinclair7d554c92016-06-20 06:06:31 -0700385
Tom Sepez016a3472015-09-30 15:50:57 -0700386 v8::Local<v8::Context> v8Context =
tsepezb4694242016-08-15 16:44:55 -0700387 v8::Context::New(m_isolate, nullptr, GetGlobalObjectTemplate(m_isolate));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700388 v8::Context::Scope context_scope(v8Context);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700389
tsepezb4694242016-08-15 16:44:55 -0700390 v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, this);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700391
tsepezb4694242016-08-15 16:44:55 -0700392 int maxID = CFXJS_ObjDefinition::MaxID(m_isolate);
393 m_StaticObjects.resize(maxID + 1);
Tom Sepezed7b2b52015-09-22 08:36:17 -0700394 for (int i = 0; i < maxID; ++i) {
tsepezb4694242016-08-15 16:44:55 -0700395 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(m_isolate, i);
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700396 if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) {
Tom Sepez3f72fb42017-02-27 11:43:55 -0800397 CFXJS_PerObjectData::SetInObject(new CFXJS_PerObjectData(i),
398 v8Context->Global()
399 ->GetPrototype()
400 ->ToObject(v8Context)
401 .ToLocalChecked());
402 if (pObjDef->m_pConstructor) {
tsepezb4694242016-08-15 16:44:55 -0700403 pObjDef->m_pConstructor(this, v8Context->Global()
404 ->GetPrototype()
405 ->ToObject(v8Context)
406 .ToLocalChecked());
Tom Sepez3f72fb42017-02-27 11:43:55 -0800407 }
Tom Sepezcd56a7d2015-10-06 11:45:28 -0700408 } else if (pObjDef->m_ObjType == FXJSOBJTYPE_STATIC) {
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700409 v8::Local<v8::String> pObjName = NewString(pObjDef->m_ObjName);
tsepezb4694242016-08-15 16:44:55 -0700410 v8::Local<v8::Object> obj = NewFxDynamicObj(i, true);
Tom Sepez63b2fc72017-08-14 16:24:29 -0700411 if (!obj.IsEmpty()) {
412 v8Context->Global()->Set(v8Context, pObjName, obj).FromJust();
413 m_StaticObjects[i] = new v8::Global<v8::Object>(m_isolate, obj);
414 } else {
415 m_StaticObjects[i] = nullptr;
416 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700417 }
418 }
tsepezb4694242016-08-15 16:44:55 -0700419 m_V8PersistentContext.Reset(m_isolate, v8Context);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700420}
421
tsepezb4694242016-08-15 16:44:55 -0700422void CFXJS_Engine::ReleaseEngine() {
423 v8::Isolate::Scope isolate_scope(m_isolate);
424 v8::HandleScope handle_scope(m_isolate);
Tom Sepez808a99e2015-09-10 12:28:37 -0700425 v8::Local<v8::Context> context =
tsepezb4694242016-08-15 16:44:55 -0700426 v8::Local<v8::Context>::New(m_isolate, m_V8PersistentContext);
Tom Sepez808a99e2015-09-10 12:28:37 -0700427 v8::Context::Scope context_scope(context);
tsepezb4694242016-08-15 16:44:55 -0700428 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_isolate);
Tom Sepez129a60e2016-03-24 09:19:20 -0700429 if (!pData)
430 return;
Tom Sepez129a60e2016-03-24 09:19:20 -0700431
tsepezb4694242016-08-15 16:44:55 -0700432 m_ConstArrays.clear();
433
434 int maxID = CFXJS_ObjDefinition::MaxID(m_isolate);
Tom Sepezed7b2b52015-09-22 08:36:17 -0700435 for (int i = 0; i < maxID; ++i) {
tsepezb4694242016-08-15 16:44:55 -0700436 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(m_isolate, i);
Oliver Chang8f16b692015-10-27 09:34:49 -0700437 v8::Local<v8::Object> pObj;
438 if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) {
439 pObj =
440 context->Global()->GetPrototype()->ToObject(context).ToLocalChecked();
tsepezb4694242016-08-15 16:44:55 -0700441 } else if (m_StaticObjects[i] && !m_StaticObjects[i]->IsEmpty()) {
442 pObj = v8::Local<v8::Object>::New(m_isolate, *m_StaticObjects[i]);
443 delete m_StaticObjects[i];
444 m_StaticObjects[i] = nullptr;
Oliver Chang8f16b692015-10-27 09:34:49 -0700445 }
446
447 if (!pObj.IsEmpty()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 if (pObjDef->m_pDestructor)
tsepezb4694242016-08-15 16:44:55 -0700449 pObjDef->m_pDestructor(this, pObj);
450 FreeObjectPrivate(pObj);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700451 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700452 }
Tom Sepez808a99e2015-09-10 12:28:37 -0700453
tsepezb4694242016-08-15 16:44:55 -0700454 m_V8PersistentContext.Reset();
455
456 if (m_isolate == g_isolate && --g_isolate_ref_count > 0)
Tom Sepez4237aed2015-11-10 15:19:17 -0800457 return;
458
Tom Sepez129a60e2016-03-24 09:19:20 -0700459 delete pData;
weilia4ad5952016-09-22 10:38:53 -0700460 m_isolate->SetData(g_embedderDataSlot, nullptr);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700461}
462
Ryan Harrison275e2602017-09-18 14:23:18 -0400463int CFXJS_Engine::Execute(const WideString& script, FXJSErr* pError) {
tsepezb4694242016-08-15 16:44:55 -0700464 v8::Isolate::Scope isolate_scope(m_isolate);
465 v8::TryCatch try_catch(m_isolate);
tsepezb4694242016-08-15 16:44:55 -0700466 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700467 v8::Local<v8::Script> compiled_script;
Ryan Harrison275e2602017-09-18 14:23:18 -0400468 if (!v8::Script::Compile(context, NewString(script.AsStringView()))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700469 .ToLocal(&compiled_script)) {
470 v8::String::Utf8Value error(try_catch.Exception());
Tom Sepez39bfe122015-09-17 15:25:23 -0700471 // TODO(tsepez): return error via pError->message.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700472 return -1;
473 }
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700474
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700475 v8::Local<v8::Value> result;
476 if (!compiled_script->Run(context).ToLocal(&result)) {
477 v8::String::Utf8Value error(try_catch.Exception());
Tom Sepez39bfe122015-09-17 15:25:23 -0700478 // TODO(tsepez): return error via pError->message.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700479 return -1;
480 }
481 return 0;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700482}
483
tsepezb4694242016-08-15 16:44:55 -0700484v8::Local<v8::Object> CFXJS_Engine::NewFxDynamicObj(int nObjDefnID,
485 bool bStatic) {
486 v8::Isolate::Scope isolate_scope(m_isolate);
487 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Tom Sepezed7b2b52015-09-22 08:36:17 -0700488 if (nObjDefnID == -1) {
tsepezb4694242016-08-15 16:44:55 -0700489 v8::Local<v8::ObjectTemplate> objTempl = v8::ObjectTemplate::New(m_isolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490 v8::Local<v8::Object> obj;
Tom Sepez016a3472015-09-30 15:50:57 -0700491 if (!objTempl->NewInstance(context).ToLocal(&obj))
492 return v8::Local<v8::Object>();
493 return obj;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700494 }
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700495
tsepezb4694242016-08-15 16:44:55 -0700496 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_isolate);
Tom Sepezed7b2b52015-09-22 08:36:17 -0700497 if (!pData)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700498 return v8::Local<v8::Object>();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700499
tsepezb4694242016-08-15 16:44:55 -0700500 if (nObjDefnID < 0 || nObjDefnID >= CFXJS_ObjDefinition::MaxID(m_isolate))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700501 return v8::Local<v8::Object>();
Tom Sepezed7b2b52015-09-22 08:36:17 -0700502
503 CFXJS_ObjDefinition* pObjDef =
tsepezb4694242016-08-15 16:44:55 -0700504 CFXJS_ObjDefinition::ForID(m_isolate, nObjDefnID);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505 v8::Local<v8::Object> obj;
Tom Sepez016a3472015-09-30 15:50:57 -0700506 if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700507 return v8::Local<v8::Object>();
Tom Sepez39bfe122015-09-17 15:25:23 -0700508
Tom Sepez3f72fb42017-02-27 11:43:55 -0800509 CFXJS_PerObjectData* pObjData = new CFXJS_PerObjectData(nObjDefnID);
510 CFXJS_PerObjectData::SetInObject(pObjData, obj);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700511 if (pObjDef->m_pConstructor)
tsepezb4694242016-08-15 16:44:55 -0700512 pObjDef->m_pConstructor(this, obj);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700513
Tom Sepez3f72fb42017-02-27 11:43:55 -0800514 if (!bStatic && FXJS_PerIsolateData::Get(m_isolate)->m_pDynamicObjsMap)
515 FXJS_PerIsolateData::Get(m_isolate)->m_pDynamicObjsMap->set(pObjData, obj);
516
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517 return obj;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700518}
519
tsepezb4694242016-08-15 16:44:55 -0700520v8::Local<v8::Object> CFXJS_Engine::GetThisObj() {
521 v8::Isolate::Scope isolate_scope(m_isolate);
522 if (!FXJS_PerIsolateData::Get(m_isolate))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700523 return v8::Local<v8::Object>();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700524
Tom Sepezed7b2b52015-09-22 08:36:17 -0700525 // Return the global object.
tsepezb4694242016-08-15 16:44:55 -0700526 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700527 return context->Global()->GetPrototype()->ToObject(context).ToLocalChecked();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700528}
529
Ryan Harrison275e2602017-09-18 14:23:18 -0400530void CFXJS_Engine::Error(const WideString& message) {
531 m_isolate->ThrowException(NewString(message.AsStringView()));
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700532}
533
tsepezb4694242016-08-15 16:44:55 -0700534void CFXJS_Engine::SetObjectPrivate(v8::Local<v8::Object> pObj, void* p) {
Tom Sepez3f72fb42017-02-27 11:43:55 -0800535 CFXJS_PerObjectData* pPerObjectData =
536 CFXJS_PerObjectData::GetFromObject(pObj);
Tom Sepez6cf117c2015-11-06 14:52:10 -0800537 if (!pPerObjectData)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700538 return;
Tom Sepez6cf117c2015-11-06 14:52:10 -0800539 pPerObjectData->m_pPrivate = p;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700540}
541
tsepezb4694242016-08-15 16:44:55 -0700542void* CFXJS_Engine::GetObjectPrivate(v8::Local<v8::Object> pObj) {
Tom Sepez3f72fb42017-02-27 11:43:55 -0800543 CFXJS_PerObjectData* pData = CFXJS_PerObjectData::GetFromObject(pObj);
544 if (!pData && !pObj.IsEmpty()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700545 // It could be a global proxy object.
546 v8::Local<v8::Value> v = pObj->GetPrototype();
tsepezb4694242016-08-15 16:44:55 -0700547 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Lei Zhang4d4a4422015-10-08 12:00:14 -0700548 if (v->IsObject()) {
Tom Sepez3f72fb42017-02-27 11:43:55 -0800549 pData = CFXJS_PerObjectData::GetFromObject(
550 v->ToObject(context).ToLocalChecked());
Lei Zhang4d4a4422015-10-08 12:00:14 -0700551 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700552 }
Tom Sepez3f72fb42017-02-27 11:43:55 -0800553 return pData ? pData->m_pPrivate : nullptr;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700554}
555
tsepezb4694242016-08-15 16:44:55 -0700556v8::Local<v8::Value> CFXJS_Engine::GetObjectProperty(
tsepez018935c2016-04-15 13:15:12 -0700557 v8::Local<v8::Object> pObj,
Ryan Harrison275e2602017-09-18 14:23:18 -0400558 const WideString& wsPropertyName) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 if (pObj.IsEmpty())
560 return v8::Local<v8::Value>();
561 v8::Local<v8::Value> val;
Tom Sepezc6dc69f2017-02-23 09:53:09 -0800562 if (!pObj->Get(m_isolate->GetCurrentContext(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400563 NewString(wsPropertyName.AsStringView()))
Dan Sinclairf766ad22016-03-14 13:51:24 -0400564 .ToLocal(&val))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700565 return v8::Local<v8::Value>();
566 return val;
567}
568
Ryan Harrison275e2602017-09-18 14:23:18 -0400569std::vector<WideString> CFXJS_Engine::GetObjectPropertyNames(
tsepezd0b6ed12016-08-11 19:50:57 -0700570 v8::Local<v8::Object> pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700571 if (pObj.IsEmpty())
Ryan Harrison275e2602017-09-18 14:23:18 -0400572 return std::vector<WideString>();
tsepezd0b6ed12016-08-11 19:50:57 -0700573
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700574 v8::Local<v8::Array> val;
tsepezb4694242016-08-15 16:44:55 -0700575 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
576 if (!pObj->GetPropertyNames(context).ToLocal(&val))
Ryan Harrison275e2602017-09-18 14:23:18 -0400577 return std::vector<WideString>();
tsepezd0b6ed12016-08-11 19:50:57 -0700578
Ryan Harrison275e2602017-09-18 14:23:18 -0400579 std::vector<WideString> result;
tsepezd0b6ed12016-08-11 19:50:57 -0700580 for (uint32_t i = 0; i < val->Length(); ++i) {
tsepeze6cf0132017-01-18 14:38:18 -0800581 result.push_back(ToWideString(val->Get(context, i).ToLocalChecked()));
tsepezd0b6ed12016-08-11 19:50:57 -0700582 }
583
584 return result;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700585}
586
tsepeze6cf0132017-01-18 14:38:18 -0800587void CFXJS_Engine::PutObjectProperty(v8::Local<v8::Object> pObj,
Ryan Harrison275e2602017-09-18 14:23:18 -0400588 const WideString& wsPropertyName,
tsepeze6cf0132017-01-18 14:38:18 -0800589 v8::Local<v8::Value> pPut) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700590 if (pObj.IsEmpty())
591 return;
Tom Sepezc6dc69f2017-02-23 09:53:09 -0800592 pObj->Set(m_isolate->GetCurrentContext(),
Ryan Harrison275e2602017-09-18 14:23:18 -0400593 NewString(wsPropertyName.AsStringView()), pPut)
Dan Sinclairf766ad22016-03-14 13:51:24 -0400594 .FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700595}
596
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700597
tsepezb4694242016-08-15 16:44:55 -0700598v8::Local<v8::Array> CFXJS_Engine::NewArray() {
599 return v8::Array::New(m_isolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700600}
601
tsepezb4694242016-08-15 16:44:55 -0700602unsigned CFXJS_Engine::PutArrayElement(v8::Local<v8::Array> pArray,
603 unsigned index,
604 v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700605 if (pArray.IsEmpty())
606 return 0;
tsepezb4694242016-08-15 16:44:55 -0700607 if (pArray->Set(m_isolate->GetCurrentContext(), index, pValue).IsNothing())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700608 return 0;
609 return 1;
610}
611
tsepezb4694242016-08-15 16:44:55 -0700612v8::Local<v8::Value> CFXJS_Engine::GetArrayElement(v8::Local<v8::Array> pArray,
613 unsigned index) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700614 if (pArray.IsEmpty())
615 return v8::Local<v8::Value>();
616 v8::Local<v8::Value> val;
tsepezb4694242016-08-15 16:44:55 -0700617 if (!pArray->Get(m_isolate->GetCurrentContext(), index).ToLocal(&val))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700618 return v8::Local<v8::Value>();
619 return val;
620}
621
tsepezb4694242016-08-15 16:44:55 -0700622unsigned CFXJS_Engine::GetArrayLength(v8::Local<v8::Array> pArray) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700623 if (pArray.IsEmpty())
624 return 0;
625 return pArray->Length();
626}
627
tsepezb4694242016-08-15 16:44:55 -0700628v8::Local<v8::Context> CFXJS_Engine::NewLocalContext() {
629 return v8::Local<v8::Context>::New(m_isolate, m_V8PersistentContext);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700630}
631
tsepezb4694242016-08-15 16:44:55 -0700632v8::Local<v8::Context> CFXJS_Engine::GetPersistentContext() {
633 return m_V8PersistentContext.Get(m_isolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700634}
635
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700636v8::Local<v8::Number> CFXJS_Engine::NewNumber(int number) {
tsepezb4694242016-08-15 16:44:55 -0700637 return v8::Int32::New(m_isolate, number);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700638}
639
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700640v8::Local<v8::Number> CFXJS_Engine::NewNumber(double number) {
tsepezb4694242016-08-15 16:44:55 -0700641 return v8::Number::New(m_isolate, number);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700642}
643
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700644v8::Local<v8::Number> CFXJS_Engine::NewNumber(float number) {
tsepezb4694242016-08-15 16:44:55 -0700645 return v8::Number::New(m_isolate, (float)number);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700646}
647
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700648v8::Local<v8::Boolean> CFXJS_Engine::NewBoolean(bool b) {
tsepezb4694242016-08-15 16:44:55 -0700649 return v8::Boolean::New(m_isolate, b);
650}
651
Ryan Harrison275e2602017-09-18 14:23:18 -0400652v8::Local<v8::String> CFXJS_Engine::NewString(const ByteStringView& str) {
Tom Sepezc6dc69f2017-02-23 09:53:09 -0800653 v8::Isolate* pIsolate = m_isolate ? m_isolate : v8::Isolate::GetCurrent();
Tom Sepez33b42e42017-07-19 13:19:12 -0700654 return v8::String::NewFromUtf8(pIsolate, str.unterminated_c_str(),
Tom Sepezc6dc69f2017-02-23 09:53:09 -0800655 v8::NewStringType::kNormal, str.GetLength())
656 .ToLocalChecked();
657}
658
Ryan Harrison275e2602017-09-18 14:23:18 -0400659v8::Local<v8::String> CFXJS_Engine::NewString(const WideStringView& str) {
Tom Sepezf6ca07b2017-06-01 09:17:18 -0700660 // Conversion from pdfium's wchar_t wide-strings to v8's uint16_t
661 // wide-strings isn't handled by v8, so use UTF8 as a common
662 // intermediate format.
Ryan Harrison275e2602017-09-18 14:23:18 -0400663 return NewString(FX_UTF8Encode(str).AsStringView());
tsepezb4694242016-08-15 16:44:55 -0700664}
665
666v8::Local<v8::Value> CFXJS_Engine::NewNull() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700667 return v8::Local<v8::Value>();
668}
669
tsepezb4694242016-08-15 16:44:55 -0700670v8::Local<v8::Date> CFXJS_Engine::NewDate(double d) {
671 return v8::Date::New(m_isolate->GetCurrentContext(), d)
tsepez135b9982016-08-05 09:32:50 -0700672 .ToLocalChecked()
673 .As<v8::Date>();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700674}
675
tsepezb4694242016-08-15 16:44:55 -0700676int CFXJS_Engine::ToInt32(v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700677 if (pValue.IsEmpty())
678 return 0;
tsepezb4694242016-08-15 16:44:55 -0700679 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Tom Sepezfb7021c2017-05-31 10:29:25 -0700680 v8::MaybeLocal<v8::Int32> maybe_int32 = pValue->ToInt32(context);
681 if (maybe_int32.IsEmpty())
682 return 0;
683 return maybe_int32.ToLocalChecked()->Value();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700684}
685
tsepezb4694242016-08-15 16:44:55 -0700686bool CFXJS_Engine::ToBoolean(v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700687 if (pValue.IsEmpty())
688 return false;
tsepezb4694242016-08-15 16:44:55 -0700689 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Tom Sepezfb7021c2017-05-31 10:29:25 -0700690 v8::MaybeLocal<v8::Boolean> maybe_boolean = pValue->ToBoolean(context);
691 if (maybe_boolean.IsEmpty())
692 return false;
693 return maybe_boolean.ToLocalChecked()->Value();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700694}
695
tsepeze6cf0132017-01-18 14:38:18 -0800696double CFXJS_Engine::ToDouble(v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700697 if (pValue.IsEmpty())
698 return 0.0;
tsepezb4694242016-08-15 16:44:55 -0700699 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Tom Sepezfb7021c2017-05-31 10:29:25 -0700700 v8::MaybeLocal<v8::Number> maybe_number = pValue->ToNumber(context);
701 if (maybe_number.IsEmpty())
702 return 0.0;
703 return maybe_number.ToLocalChecked()->Value();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700704}
705
Ryan Harrison275e2602017-09-18 14:23:18 -0400706WideString CFXJS_Engine::ToWideString(v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700707 if (pValue.IsEmpty())
Ryan Harrison275e2602017-09-18 14:23:18 -0400708 return WideString();
tsepezb4694242016-08-15 16:44:55 -0700709 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Tom Sepezfb7021c2017-05-31 10:29:25 -0700710 v8::MaybeLocal<v8::String> maybe_string = pValue->ToString(context);
711 if (maybe_string.IsEmpty())
Ryan Harrison275e2602017-09-18 14:23:18 -0400712 return WideString();
Tom Sepezfb7021c2017-05-31 10:29:25 -0700713 v8::String::Utf8Value s(maybe_string.ToLocalChecked());
Ryan Harrison275e2602017-09-18 14:23:18 -0400714 return WideString::FromUTF8(ByteStringView(*s, s.length()));
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700715}
716
tsepeze6cf0132017-01-18 14:38:18 -0800717v8::Local<v8::Object> CFXJS_Engine::ToObject(v8::Local<v8::Value> pValue) {
718 if (pValue.IsEmpty() || !pValue->IsObject())
719 return v8::Local<v8::Object>();
720 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
721 return pValue->ToObject(context).ToLocalChecked();
722}
723
tsepezb4694242016-08-15 16:44:55 -0700724v8::Local<v8::Array> CFXJS_Engine::ToArray(v8::Local<v8::Value> pValue) {
tsepeze6cf0132017-01-18 14:38:18 -0800725 if (pValue.IsEmpty() || !pValue->IsArray())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700726 return v8::Local<v8::Array>();
tsepezb4694242016-08-15 16:44:55 -0700727 v8::Local<v8::Context> context = m_isolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700728 return v8::Local<v8::Array>::Cast(pValue->ToObject(context).ToLocalChecked());
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700729}
tsepezb4694242016-08-15 16:44:55 -0700730
Ryan Harrison275e2602017-09-18 14:23:18 -0400731void CFXJS_Engine::SetConstArray(const WideString& name,
tsepezb4694242016-08-15 16:44:55 -0700732 v8::Local<v8::Array> array) {
733 m_ConstArrays[name] = v8::Global<v8::Array>(GetIsolate(), array);
734}
735
Ryan Harrison275e2602017-09-18 14:23:18 -0400736v8::Local<v8::Array> CFXJS_Engine::GetConstArray(const WideString& name) {
tsepezb4694242016-08-15 16:44:55 -0700737 return v8::Local<v8::Array>::New(GetIsolate(), m_ConstArrays[name]);
738}