Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: fpdfsdk/jsapi/fxjs_v8.cpp

Issue 2144603003: Move fpdfsdk/jsapi into fxjs/ (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@fxjs_v8_v2_p2
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « fpdfsdk/javascript/cjs_runtime.h ('k') | fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // 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.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "fpdfsdk/jsapi/include/fxjs_v8.h"
8
9 #include <vector>
10
11 #include "core/fxcrt/include/fx_basic.h"
12
13 const wchar_t kFXJSValueNameString[] = L"string";
14 const wchar_t kFXJSValueNameNumber[] = L"number";
15 const wchar_t kFXJSValueNameBoolean[] = L"boolean";
16 const wchar_t kFXJSValueNameDate[] = L"date";
17 const wchar_t kFXJSValueNameObject[] = L"object";
18 const wchar_t kFXJSValueNameFxobj[] = L"fxobj";
19 const wchar_t kFXJSValueNameNull[] = L"null";
20 const wchar_t kFXJSValueNameUndefined[] = L"undefined";
21
22 // Keep this consistent with the values defined in gin/public/context_holder.h
23 // (without actually requiring a dependency on gin itself for the standalone
24 // embedders of PDFIum). The value we want to use is:
25 // kPerContextDataStartIndex + kEmbedderPDFium, which is 3.
26 static const unsigned int kPerContextDataIndex = 3u;
27 static unsigned int g_embedderDataSlot = 1u;
28 static v8::Isolate* g_isolate = nullptr;
29 static size_t g_isolate_ref_count = 0;
30 static FXJS_ArrayBufferAllocator* g_arrayBufferAllocator = nullptr;
31 static v8::Global<v8::ObjectTemplate>* g_DefaultGlobalObjectTemplate = nullptr;
32
33 class CFXJS_PerObjectData {
34 public:
35 explicit CFXJS_PerObjectData(int nObjDefID)
36 : m_ObjDefID(nObjDefID), m_pPrivate(nullptr) {}
37
38 const int m_ObjDefID;
39 void* m_pPrivate;
40 };
41
42 class CFXJS_ObjDefinition {
43 public:
44 static int MaxID(v8::Isolate* pIsolate) {
45 return FXJS_PerIsolateData::Get(pIsolate)->m_ObjectDefnArray.size();
46 }
47
48 static CFXJS_ObjDefinition* ForID(v8::Isolate* pIsolate, int id) {
49 // Note: GetAt() halts if out-of-range even in release builds.
50 return FXJS_PerIsolateData::Get(pIsolate)->m_ObjectDefnArray[id];
51 }
52
53 CFXJS_ObjDefinition(v8::Isolate* isolate,
54 const wchar_t* sObjName,
55 FXJSOBJTYPE eObjType,
56 FXJS_CONSTRUCTOR pConstructor,
57 FXJS_DESTRUCTOR pDestructor)
58 : m_ObjName(sObjName),
59 m_ObjType(eObjType),
60 m_pConstructor(pConstructor),
61 m_pDestructor(pDestructor),
62 m_pIsolate(isolate) {
63 v8::Isolate::Scope isolate_scope(isolate);
64 v8::HandleScope handle_scope(isolate);
65
66 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate);
67 fun->InstanceTemplate()->SetInternalFieldCount(2);
68 if (eObjType == FXJSOBJTYPE_GLOBAL) {
69 fun->InstanceTemplate()->Set(
70 v8::Symbol::GetToStringTag(isolate),
71 v8::String::NewFromUtf8(isolate, "global", v8::NewStringType::kNormal)
72 .ToLocalChecked());
73 }
74 m_FunctionTemplate.Reset(isolate, fun);
75
76 v8::Local<v8::Signature> sig = v8::Signature::New(isolate, fun);
77 m_Signature.Reset(isolate, sig);
78 }
79
80 int AssignID() {
81 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(m_pIsolate);
82 pData->m_ObjectDefnArray.push_back(this);
83 return pData->m_ObjectDefnArray.size() - 1;
84 }
85
86 v8::Local<v8::ObjectTemplate> GetInstanceTemplate() {
87 v8::EscapableHandleScope scope(m_pIsolate);
88 v8::Local<v8::FunctionTemplate> function =
89 m_FunctionTemplate.Get(m_pIsolate);
90 return scope.Escape(function->InstanceTemplate());
91 }
92
93 v8::Local<v8::Signature> GetSignature() {
94 v8::EscapableHandleScope scope(m_pIsolate);
95 return scope.Escape(m_Signature.Get(m_pIsolate));
96 }
97
98 const wchar_t* const m_ObjName;
99 const FXJSOBJTYPE m_ObjType;
100 const FXJS_CONSTRUCTOR m_pConstructor;
101 const FXJS_DESTRUCTOR m_pDestructor;
102
103 v8::Isolate* m_pIsolate;
104 v8::Global<v8::FunctionTemplate> m_FunctionTemplate;
105 v8::Global<v8::Signature> m_Signature;
106 };
107
108 static v8::Local<v8::ObjectTemplate> GetGlobalObjectTemplate(
109 v8::Isolate* pIsolate) {
110 int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
111 for (int i = 0; i < maxID; ++i) {
112 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
113 if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL)
114 return pObjDef->GetInstanceTemplate();
115 }
116 if (!g_DefaultGlobalObjectTemplate) {
117 v8::Local<v8::ObjectTemplate> hGlobalTemplate =
118 v8::ObjectTemplate::New(pIsolate);
119 hGlobalTemplate->Set(
120 v8::Symbol::GetToStringTag(pIsolate),
121 v8::String::NewFromUtf8(pIsolate, "global", v8::NewStringType::kNormal)
122 .ToLocalChecked());
123 g_DefaultGlobalObjectTemplate =
124 new v8::Global<v8::ObjectTemplate>(pIsolate, hGlobalTemplate);
125 }
126 return g_DefaultGlobalObjectTemplate->Get(pIsolate);
127 }
128
129 void* FXJS_ArrayBufferAllocator::Allocate(size_t length) {
130 return calloc(1, length);
131 }
132
133 void* FXJS_ArrayBufferAllocator::AllocateUninitialized(size_t length) {
134 return malloc(length);
135 }
136
137 void FXJS_ArrayBufferAllocator::Free(void* data, size_t length) {
138 free(data);
139 }
140
141 void V8TemplateMapTraits::Dispose(v8::Isolate* isolate,
142 v8::Global<v8::Object> value,
143 void* key) {
144 v8::Local<v8::Object> obj = value.Get(isolate);
145 if (obj.IsEmpty())
146 return;
147 int id = FXJS_GetObjDefnID(obj);
148 if (id == -1)
149 return;
150
151 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(isolate, id);
152 if (!pObjDef)
153 return;
154 if (pObjDef->m_pDestructor)
155 pObjDef->m_pDestructor(obj);
156 FXJS_FreePrivate(obj);
157 }
158
159 V8TemplateMapTraits::MapType* V8TemplateMapTraits::MapFromWeakCallbackInfo(
160 const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
161 V8TemplateMap* pMap =
162 (FXJS_PerIsolateData::Get(data.GetIsolate()))->m_pDynamicObjsMap;
163 return pMap ? &pMap->m_map : nullptr;
164 }
165
166 void FXJS_Initialize(unsigned int embedderDataSlot, v8::Isolate* pIsolate) {
167 if (g_isolate) {
168 ASSERT(g_embedderDataSlot == embedderDataSlot);
169 ASSERT(g_isolate == pIsolate);
170 return;
171 }
172 g_embedderDataSlot = embedderDataSlot;
173 g_isolate = pIsolate;
174 }
175
176 void FXJS_Release() {
177 ASSERT(!g_isolate || g_isolate_ref_count == 0);
178 delete g_DefaultGlobalObjectTemplate;
179 g_DefaultGlobalObjectTemplate = nullptr;
180 g_isolate = nullptr;
181
182 delete g_arrayBufferAllocator;
183 g_arrayBufferAllocator = nullptr;
184 }
185
186 bool FXJS_GetIsolate(v8::Isolate** pResultIsolate) {
187 if (g_isolate) {
188 *pResultIsolate = g_isolate;
189 return false;
190 }
191 // Provide backwards compatibility when no external isolate.
192 if (!g_arrayBufferAllocator)
193 g_arrayBufferAllocator = new FXJS_ArrayBufferAllocator();
194 v8::Isolate::CreateParams params;
195 params.array_buffer_allocator = g_arrayBufferAllocator;
196 *pResultIsolate = v8::Isolate::New(params);
197 return true;
198 }
199
200 size_t FXJS_GlobalIsolateRefCount() {
201 return g_isolate_ref_count;
202 }
203
204 V8TemplateMap::V8TemplateMap(v8::Isolate* isolate) : m_map(isolate) {}
205
206 V8TemplateMap::~V8TemplateMap() {}
207
208 void V8TemplateMap::set(void* key, v8::Local<v8::Object> handle) {
209 ASSERT(!m_map.Contains(key));
210 m_map.Set(key, handle);
211 }
212
213 FXJS_PerIsolateData::~FXJS_PerIsolateData() {}
214
215 // static
216 void FXJS_PerIsolateData::SetUp(v8::Isolate* pIsolate) {
217 if (!pIsolate->GetData(g_embedderDataSlot))
218 pIsolate->SetData(g_embedderDataSlot, new FXJS_PerIsolateData());
219 }
220
221 // static
222 FXJS_PerIsolateData* FXJS_PerIsolateData::Get(v8::Isolate* pIsolate) {
223 return static_cast<FXJS_PerIsolateData*>(
224 pIsolate->GetData(g_embedderDataSlot));
225 }
226
227 #ifndef PDF_ENABLE_XFA
228 FXJS_PerIsolateData::FXJS_PerIsolateData() : m_pDynamicObjsMap(nullptr) {}
229 #else // PDF_ENABLE_XFA
230 FXJS_PerIsolateData::FXJS_PerIsolateData()
231 : m_pFXJSERuntimeData(nullptr), m_pDynamicObjsMap(nullptr) {}
232 #endif // PDF_ENABLE_XFA
233
234 int FXJS_DefineObj(v8::Isolate* pIsolate,
235 const wchar_t* sObjName,
236 FXJSOBJTYPE eObjType,
237 FXJS_CONSTRUCTOR pConstructor,
238 FXJS_DESTRUCTOR pDestructor) {
239 v8::Isolate::Scope isolate_scope(pIsolate);
240 v8::HandleScope handle_scope(pIsolate);
241
242 FXJS_PerIsolateData::SetUp(pIsolate);
243 CFXJS_ObjDefinition* pObjDef = new CFXJS_ObjDefinition(
244 pIsolate, sObjName, eObjType, pConstructor, pDestructor);
245 return pObjDef->AssignID();
246 }
247
248 void FXJS_DefineObjMethod(v8::Isolate* pIsolate,
249 int nObjDefnID,
250 const wchar_t* sMethodName,
251 v8::FunctionCallback pMethodCall) {
252 v8::Isolate::Scope isolate_scope(pIsolate);
253 v8::HandleScope handle_scope(pIsolate);
254 CFX_ByteString bsMethodName = CFX_WideString(sMethodName).UTF8Encode();
255 CFXJS_ObjDefinition* pObjDef =
256 CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
257 v8::Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(
258 pIsolate, pMethodCall, v8::Local<v8::Value>(), pObjDef->GetSignature());
259 fun->RemovePrototype();
260 pObjDef->GetInstanceTemplate()->Set(
261 v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
262 v8::NewStringType::kNormal)
263 .ToLocalChecked(),
264 fun, v8::ReadOnly);
265 }
266
267 void FXJS_DefineObjProperty(v8::Isolate* pIsolate,
268 int nObjDefnID,
269 const wchar_t* sPropName,
270 v8::AccessorGetterCallback pPropGet,
271 v8::AccessorSetterCallback pPropPut) {
272 v8::Isolate::Scope isolate_scope(pIsolate);
273 v8::HandleScope handle_scope(pIsolate);
274 CFX_ByteString bsPropertyName = CFX_WideString(sPropName).UTF8Encode();
275 CFXJS_ObjDefinition* pObjDef =
276 CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
277 pObjDef->GetInstanceTemplate()->SetAccessor(
278 v8::String::NewFromUtf8(pIsolate, bsPropertyName.c_str(),
279 v8::NewStringType::kNormal)
280 .ToLocalChecked(),
281 pPropGet, pPropPut);
282 }
283
284 void FXJS_DefineObjAllProperties(v8::Isolate* pIsolate,
285 int nObjDefnID,
286 v8::NamedPropertyQueryCallback pPropQurey,
287 v8::NamedPropertyGetterCallback pPropGet,
288 v8::NamedPropertySetterCallback pPropPut,
289 v8::NamedPropertyDeleterCallback pPropDel) {
290 v8::Isolate::Scope isolate_scope(pIsolate);
291 v8::HandleScope handle_scope(pIsolate);
292 CFXJS_ObjDefinition* pObjDef =
293 CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
294 pObjDef->GetInstanceTemplate()->SetNamedPropertyHandler(pPropGet, pPropPut,
295 pPropQurey, pPropDel);
296 }
297
298 void FXJS_DefineObjConst(v8::Isolate* pIsolate,
299 int nObjDefnID,
300 const wchar_t* sConstName,
301 v8::Local<v8::Value> pDefault) {
302 v8::Isolate::Scope isolate_scope(pIsolate);
303 v8::HandleScope handle_scope(pIsolate);
304 CFX_ByteString bsConstName = CFX_WideString(sConstName).UTF8Encode();
305 CFXJS_ObjDefinition* pObjDef =
306 CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
307 pObjDef->GetInstanceTemplate()->Set(pIsolate, bsConstName.c_str(), pDefault);
308 }
309
310 void FXJS_DefineGlobalMethod(v8::Isolate* pIsolate,
311 const wchar_t* sMethodName,
312 v8::FunctionCallback pMethodCall) {
313 v8::Isolate::Scope isolate_scope(pIsolate);
314 v8::HandleScope handle_scope(pIsolate);
315 CFX_ByteString bsMethodName = CFX_WideString(sMethodName).UTF8Encode();
316 v8::Local<v8::FunctionTemplate> fun =
317 v8::FunctionTemplate::New(pIsolate, pMethodCall);
318 fun->RemovePrototype();
319 GetGlobalObjectTemplate(pIsolate)->Set(
320 v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
321 v8::NewStringType::kNormal)
322 .ToLocalChecked(),
323 fun, v8::ReadOnly);
324 }
325
326 void FXJS_DefineGlobalConst(v8::Isolate* pIsolate,
327 const wchar_t* sConstName,
328 v8::FunctionCallback pConstGetter) {
329 v8::Isolate::Scope isolate_scope(pIsolate);
330 v8::HandleScope handle_scope(pIsolate);
331 CFX_ByteString bsConst = CFX_WideString(sConstName).UTF8Encode();
332 v8::Local<v8::FunctionTemplate> fun =
333 v8::FunctionTemplate::New(pIsolate, pConstGetter);
334 fun->RemovePrototype();
335 GetGlobalObjectTemplate(pIsolate)->SetAccessorProperty(
336 v8::String::NewFromUtf8(pIsolate, bsConst.c_str(),
337 v8::NewStringType::kNormal)
338 .ToLocalChecked(),
339 fun);
340 }
341
342 void FXJS_InitializeRuntime(
343 v8::Isolate* pIsolate,
344 IJS_Runtime* pIRuntime,
345 v8::Global<v8::Context>* pV8PersistentContext,
346 std::vector<v8::Global<v8::Object>*>* pStaticObjects) {
347 if (pIsolate == g_isolate)
348 ++g_isolate_ref_count;
349
350 v8::Isolate::Scope isolate_scope(pIsolate);
351 v8::HandleScope handle_scope(pIsolate);
352
353 // This has to happen before we call GetGlobalObjectTemplate because that
354 // method gets the PerIsolateData from pIsolate.
355 FXJS_PerIsolateData::SetUp(pIsolate);
356
357 v8::Local<v8::Context> v8Context =
358 v8::Context::New(pIsolate, nullptr, GetGlobalObjectTemplate(pIsolate));
359 v8::Context::Scope context_scope(v8Context);
360
361 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
362 if (!pData)
363 return;
364 pData->CreateDynamicObjsMap(pIsolate);
365 v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime);
366
367 int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
368 pStaticObjects->resize(maxID + 1);
369 for (int i = 0; i < maxID; ++i) {
370 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
371 if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) {
372 v8Context->Global()
373 ->GetPrototype()
374 ->ToObject(v8Context)
375 .ToLocalChecked()
376 ->SetAlignedPointerInInternalField(0, new CFXJS_PerObjectData(i));
377
378 if (pObjDef->m_pConstructor)
379 pObjDef->m_pConstructor(pIRuntime, v8Context->Global()
380 ->GetPrototype()
381 ->ToObject(v8Context)
382 .ToLocalChecked());
383 } else if (pObjDef->m_ObjType == FXJSOBJTYPE_STATIC) {
384 CFX_ByteString bs = CFX_WideString(pObjDef->m_ObjName).UTF8Encode();
385 v8::Local<v8::String> m_ObjName =
386 v8::String::NewFromUtf8(pIsolate, bs.c_str(),
387 v8::NewStringType::kNormal, bs.GetLength())
388 .ToLocalChecked();
389
390 v8::Local<v8::Object> obj =
391 FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i, true);
392 v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust();
393 pStaticObjects->at(i) = new v8::Global<v8::Object>(pIsolate, obj);
394 }
395 }
396 pV8PersistentContext->Reset(pIsolate, v8Context);
397 }
398
399 void FXJS_ReleaseRuntime(v8::Isolate* pIsolate,
400 v8::Global<v8::Context>* pV8PersistentContext,
401 std::vector<v8::Global<v8::Object>*>* pStaticObjects) {
402 v8::Isolate::Scope isolate_scope(pIsolate);
403 v8::HandleScope handle_scope(pIsolate);
404 v8::Local<v8::Context> context =
405 v8::Local<v8::Context>::New(pIsolate, *pV8PersistentContext);
406 v8::Context::Scope context_scope(context);
407
408 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
409 if (!pData)
410 return;
411
412 int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
413 for (int i = 0; i < maxID; ++i) {
414 CFXJS_ObjDefinition* pObjDef = CFXJS_ObjDefinition::ForID(pIsolate, i);
415 v8::Local<v8::Object> pObj;
416 if (pObjDef->m_ObjType == FXJSOBJTYPE_GLOBAL) {
417 pObj =
418 context->Global()->GetPrototype()->ToObject(context).ToLocalChecked();
419 } else if (pStaticObjects->at(i) && !pStaticObjects->at(i)->IsEmpty()) {
420 pObj = v8::Local<v8::Object>::New(pIsolate, *pStaticObjects->at(i));
421 delete pStaticObjects->at(i);
422 pStaticObjects->at(i) = nullptr;
423 }
424
425 if (!pObj.IsEmpty()) {
426 if (pObjDef->m_pDestructor)
427 pObjDef->m_pDestructor(pObj);
428 FXJS_FreePrivate(pObj);
429 }
430 }
431
432 if (pIsolate == g_isolate && --g_isolate_ref_count > 0)
433 return;
434
435 pData->ReleaseDynamicObjsMap();
436 for (int i = 0; i < maxID; ++i)
437 delete CFXJS_ObjDefinition::ForID(pIsolate, i);
438
439 pIsolate->SetData(g_embedderDataSlot, nullptr);
440 delete pData;
441 }
442
443 IJS_Runtime* FXJS_GetRuntimeFromIsolate(v8::Isolate* pIsolate) {
444 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
445 return static_cast<IJS_Runtime*>(
446 context->GetAlignedPointerFromEmbedderData(kPerContextDataIndex));
447 }
448
449 #ifdef PDF_ENABLE_XFA
450 void FXJS_SetRuntimeForV8Context(v8::Local<v8::Context> v8Context,
451 IJS_Runtime* pIRuntime) {
452 v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime);
453 }
454 #endif // PDF_ENABLE_XFA
455
456 int FXJS_Execute(v8::Isolate* pIsolate,
457 const CFX_WideString& script,
458 FXJSErr* pError) {
459 v8::Isolate::Scope isolate_scope(pIsolate);
460 v8::TryCatch try_catch(pIsolate);
461 CFX_ByteString bsScript = script.UTF8Encode();
462 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
463 v8::Local<v8::Script> compiled_script;
464 if (!v8::Script::Compile(context,
465 v8::String::NewFromUtf8(pIsolate, bsScript.c_str(),
466 v8::NewStringType::kNormal,
467 bsScript.GetLength())
468 .ToLocalChecked())
469 .ToLocal(&compiled_script)) {
470 v8::String::Utf8Value error(try_catch.Exception());
471 // TODO(tsepez): return error via pError->message.
472 return -1;
473 }
474
475 v8::Local<v8::Value> result;
476 if (!compiled_script->Run(context).ToLocal(&result)) {
477 v8::String::Utf8Value error(try_catch.Exception());
478 // TODO(tsepez): return error via pError->message.
479 return -1;
480 }
481 return 0;
482 }
483
484 v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
485 IJS_Runtime* pIRuntime,
486 int nObjDefnID,
487 bool bStatic) {
488 v8::Isolate::Scope isolate_scope(pIsolate);
489 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
490 if (nObjDefnID == -1) {
491 v8::Local<v8::ObjectTemplate> objTempl = v8::ObjectTemplate::New(pIsolate);
492 v8::Local<v8::Object> obj;
493 if (!objTempl->NewInstance(context).ToLocal(&obj))
494 return v8::Local<v8::Object>();
495 return obj;
496 }
497
498 FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
499 if (!pData)
500 return v8::Local<v8::Object>();
501
502 if (nObjDefnID < 0 || nObjDefnID >= CFXJS_ObjDefinition::MaxID(pIsolate))
503 return v8::Local<v8::Object>();
504
505 CFXJS_ObjDefinition* pObjDef =
506 CFXJS_ObjDefinition::ForID(pIsolate, nObjDefnID);
507 v8::Local<v8::Object> obj;
508 if (!pObjDef->GetInstanceTemplate()->NewInstance(context).ToLocal(&obj))
509 return v8::Local<v8::Object>();
510
511 CFXJS_PerObjectData* pPerObjData = new CFXJS_PerObjectData(nObjDefnID);
512 obj->SetAlignedPointerInInternalField(0, pPerObjData);
513 if (pObjDef->m_pConstructor)
514 pObjDef->m_pConstructor(pIRuntime, obj);
515
516 if (!bStatic && FXJS_PerIsolateData::Get(pIsolate)->m_pDynamicObjsMap) {
517 FXJS_PerIsolateData::Get(pIsolate)
518 ->m_pDynamicObjsMap->set(pPerObjData, obj);
519 }
520 return obj;
521 }
522
523 v8::Local<v8::Object> FXJS_GetThisObj(v8::Isolate* pIsolate) {
524 v8::Isolate::Scope isolate_scope(pIsolate);
525 if (!FXJS_PerIsolateData::Get(pIsolate))
526 return v8::Local<v8::Object>();
527
528 // Return the global object.
529 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
530 return context->Global()->GetPrototype()->ToObject(context).ToLocalChecked();
531 }
532
533 int FXJS_GetObjDefnID(v8::Local<v8::Object> pObj) {
534 if (pObj.IsEmpty() || !pObj->InternalFieldCount())
535 return -1;
536 CFXJS_PerObjectData* pPerObjectData = static_cast<CFXJS_PerObjectData*>(
537 pObj->GetAlignedPointerFromInternalField(0));
538 if (pPerObjectData)
539 return pPerObjectData->m_ObjDefID;
540 return -1;
541 }
542
543 void FXJS_Error(v8::Isolate* pIsolate, const CFX_WideString& message) {
544 // Conversion from pdfium's wchar_t wide-strings to v8's uint16_t
545 // wide-strings isn't handled by v8, so use UTF8 as a common
546 // intermediate format.
547 CFX_ByteString utf8_message = message.UTF8Encode();
548 pIsolate->ThrowException(v8::String::NewFromUtf8(pIsolate,
549 utf8_message.c_str(),
550 v8::NewStringType::kNormal)
551 .ToLocalChecked());
552 }
553
554 const wchar_t* FXJS_GetTypeof(v8::Local<v8::Value> pObj) {
555 if (pObj.IsEmpty())
556 return nullptr;
557 if (pObj->IsString())
558 return kFXJSValueNameString;
559 if (pObj->IsNumber())
560 return kFXJSValueNameNumber;
561 if (pObj->IsBoolean())
562 return kFXJSValueNameBoolean;
563 if (pObj->IsDate())
564 return kFXJSValueNameDate;
565 if (pObj->IsObject())
566 return kFXJSValueNameObject;
567 if (pObj->IsNull())
568 return kFXJSValueNameNull;
569 if (pObj->IsUndefined())
570 return kFXJSValueNameUndefined;
571 return nullptr;
572 }
573
574 void FXJS_SetPrivate(v8::Isolate* pIsolate,
575 v8::Local<v8::Object> pObj,
576 void* p) {
577 if (pObj.IsEmpty() || !pObj->InternalFieldCount())
578 return;
579 CFXJS_PerObjectData* pPerObjectData = static_cast<CFXJS_PerObjectData*>(
580 pObj->GetAlignedPointerFromInternalField(0));
581 if (!pPerObjectData)
582 return;
583 pPerObjectData->m_pPrivate = p;
584 }
585
586 void* FXJS_GetPrivate(v8::Isolate* pIsolate, v8::Local<v8::Object> pObj) {
587 if (pObj.IsEmpty())
588 return nullptr;
589 CFXJS_PerObjectData* pPerObjectData = nullptr;
590 if (pObj->InternalFieldCount()) {
591 pPerObjectData = static_cast<CFXJS_PerObjectData*>(
592 pObj->GetAlignedPointerFromInternalField(0));
593 } else {
594 // It could be a global proxy object.
595 v8::Local<v8::Value> v = pObj->GetPrototype();
596 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
597 if (v->IsObject()) {
598 pPerObjectData = static_cast<CFXJS_PerObjectData*>(
599 v->ToObject(context)
600 .ToLocalChecked()
601 ->GetAlignedPointerFromInternalField(0));
602 }
603 }
604 return pPerObjectData ? pPerObjectData->m_pPrivate : nullptr;
605 }
606
607 void FXJS_FreePrivate(void* pPerObjectData) {
608 delete static_cast<CFXJS_PerObjectData*>(pPerObjectData);
609 }
610
611 void FXJS_FreePrivate(v8::Local<v8::Object> pObj) {
612 if (pObj.IsEmpty() || !pObj->InternalFieldCount())
613 return;
614 FXJS_FreePrivate(pObj->GetAlignedPointerFromInternalField(0));
615 pObj->SetAlignedPointerInInternalField(0, nullptr);
616 }
617
618 v8::Local<v8::String> FXJS_WSToJSString(v8::Isolate* pIsolate,
619 const CFX_WideString& wsPropertyName) {
620 CFX_ByteString bs = wsPropertyName.UTF8Encode();
621 if (!pIsolate)
622 pIsolate = v8::Isolate::GetCurrent();
623 return v8::String::NewFromUtf8(pIsolate, bs.c_str(),
624 v8::NewStringType::kNormal, bs.GetLength())
625 .ToLocalChecked();
626 }
627
628 v8::Local<v8::Value> FXJS_GetObjectElement(
629 v8::Isolate* pIsolate,
630 v8::Local<v8::Object> pObj,
631 const CFX_WideString& wsPropertyName) {
632 if (pObj.IsEmpty())
633 return v8::Local<v8::Value>();
634 v8::Local<v8::Value> val;
635 if (!pObj->Get(pIsolate->GetCurrentContext(),
636 FXJS_WSToJSString(pIsolate, wsPropertyName))
637 .ToLocal(&val))
638 return v8::Local<v8::Value>();
639 return val;
640 }
641
642 v8::Local<v8::Array> FXJS_GetObjectElementNames(v8::Isolate* pIsolate,
643 v8::Local<v8::Object> pObj) {
644 if (pObj.IsEmpty())
645 return v8::Local<v8::Array>();
646 v8::Local<v8::Array> val;
647 if (!pObj->GetPropertyNames(pIsolate->GetCurrentContext()).ToLocal(&val))
648 return v8::Local<v8::Array>();
649 return val;
650 }
651
652 void FXJS_PutObjectString(v8::Isolate* pIsolate,
653 v8::Local<v8::Object> pObj,
654 const CFX_WideString& wsPropertyName,
655 const CFX_WideString& wsValue) {
656 if (pObj.IsEmpty())
657 return;
658 pObj->Set(pIsolate->GetCurrentContext(),
659 FXJS_WSToJSString(pIsolate, wsPropertyName),
660 FXJS_WSToJSString(pIsolate, wsValue))
661 .FromJust();
662 }
663
664 void FXJS_PutObjectNumber(v8::Isolate* pIsolate,
665 v8::Local<v8::Object> pObj,
666 const CFX_WideString& wsPropertyName,
667 int nValue) {
668 if (pObj.IsEmpty())
669 return;
670 pObj->Set(pIsolate->GetCurrentContext(),
671 FXJS_WSToJSString(pIsolate, wsPropertyName),
672 v8::Int32::New(pIsolate, nValue))
673 .FromJust();
674 }
675
676 void FXJS_PutObjectNumber(v8::Isolate* pIsolate,
677 v8::Local<v8::Object> pObj,
678 const CFX_WideString& wsPropertyName,
679 float fValue) {
680 if (pObj.IsEmpty())
681 return;
682 pObj->Set(pIsolate->GetCurrentContext(),
683 FXJS_WSToJSString(pIsolate, wsPropertyName),
684 v8::Number::New(pIsolate, (double)fValue))
685 .FromJust();
686 }
687
688 void FXJS_PutObjectNumber(v8::Isolate* pIsolate,
689 v8::Local<v8::Object> pObj,
690 const CFX_WideString& wsPropertyName,
691 double dValue) {
692 if (pObj.IsEmpty())
693 return;
694 pObj->Set(pIsolate->GetCurrentContext(),
695 FXJS_WSToJSString(pIsolate, wsPropertyName),
696 v8::Number::New(pIsolate, (double)dValue))
697 .FromJust();
698 }
699
700 void FXJS_PutObjectBoolean(v8::Isolate* pIsolate,
701 v8::Local<v8::Object> pObj,
702 const CFX_WideString& wsPropertyName,
703 bool bValue) {
704 if (pObj.IsEmpty())
705 return;
706 pObj->Set(pIsolate->GetCurrentContext(),
707 FXJS_WSToJSString(pIsolate, wsPropertyName),
708 v8::Boolean::New(pIsolate, bValue))
709 .FromJust();
710 }
711
712 void FXJS_PutObjectObject(v8::Isolate* pIsolate,
713 v8::Local<v8::Object> pObj,
714 const CFX_WideString& wsPropertyName,
715 v8::Local<v8::Object> pPut) {
716 if (pObj.IsEmpty())
717 return;
718 pObj->Set(pIsolate->GetCurrentContext(),
719 FXJS_WSToJSString(pIsolate, wsPropertyName), pPut)
720 .FromJust();
721 }
722
723 void FXJS_PutObjectNull(v8::Isolate* pIsolate,
724 v8::Local<v8::Object> pObj,
725 const CFX_WideString& wsPropertyName) {
726 if (pObj.IsEmpty())
727 return;
728 pObj->Set(pIsolate->GetCurrentContext(),
729 FXJS_WSToJSString(pIsolate, wsPropertyName),
730 v8::Local<v8::Object>())
731 .FromJust();
732 }
733
734 v8::Local<v8::Array> FXJS_NewArray(v8::Isolate* pIsolate) {
735 return v8::Array::New(pIsolate);
736 }
737
738 unsigned FXJS_PutArrayElement(v8::Isolate* pIsolate,
739 v8::Local<v8::Array> pArray,
740 unsigned index,
741 v8::Local<v8::Value> pValue) {
742 if (pArray.IsEmpty())
743 return 0;
744 if (pArray->Set(pIsolate->GetCurrentContext(), index, pValue).IsNothing())
745 return 0;
746 return 1;
747 }
748
749 v8::Local<v8::Value> FXJS_GetArrayElement(v8::Isolate* pIsolate,
750 v8::Local<v8::Array> pArray,
751 unsigned index) {
752 if (pArray.IsEmpty())
753 return v8::Local<v8::Value>();
754 v8::Local<v8::Value> val;
755 if (!pArray->Get(pIsolate->GetCurrentContext(), index).ToLocal(&val))
756 return v8::Local<v8::Value>();
757 return val;
758 }
759
760 unsigned FXJS_GetArrayLength(v8::Local<v8::Array> pArray) {
761 if (pArray.IsEmpty())
762 return 0;
763 return pArray->Length();
764 }
765
766 v8::Local<v8::Value> FXJS_NewNumber(v8::Isolate* pIsolate, int number) {
767 return v8::Int32::New(pIsolate, number);
768 }
769
770 v8::Local<v8::Value> FXJS_NewNumber(v8::Isolate* pIsolate, double number) {
771 return v8::Number::New(pIsolate, number);
772 }
773
774 v8::Local<v8::Value> FXJS_NewNumber(v8::Isolate* pIsolate, float number) {
775 return v8::Number::New(pIsolate, (float)number);
776 }
777
778 v8::Local<v8::Value> FXJS_NewBoolean(v8::Isolate* pIsolate, bool b) {
779 return v8::Boolean::New(pIsolate, b);
780 }
781
782 v8::Local<v8::Value> FXJS_NewObject(v8::Isolate* pIsolate,
783 v8::Local<v8::Object> pObj) {
784 if (pObj.IsEmpty())
785 return v8::Local<v8::Value>();
786 return pObj->Clone();
787 }
788
789 v8::Local<v8::Value> FXJS_NewObject2(v8::Isolate* pIsolate,
790 v8::Local<v8::Array> pObj) {
791 if (pObj.IsEmpty())
792 return v8::Local<v8::Value>();
793 return pObj->Clone();
794 }
795
796 v8::Local<v8::Value> FXJS_NewString(v8::Isolate* pIsolate, const wchar_t* str) {
797 return FXJS_WSToJSString(pIsolate, str);
798 }
799
800 v8::Local<v8::Value> FXJS_NewNull() {
801 return v8::Local<v8::Value>();
802 }
803
804 v8::Local<v8::Value> FXJS_NewDate(v8::Isolate* pIsolate, double d) {
805 return v8::Date::New(pIsolate->GetCurrentContext(), d).ToLocalChecked();
806 }
807
808 int FXJS_ToInt32(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
809 if (pValue.IsEmpty())
810 return 0;
811 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
812 return pValue->ToInt32(context).ToLocalChecked()->Value();
813 }
814
815 bool FXJS_ToBoolean(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
816 if (pValue.IsEmpty())
817 return false;
818 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
819 return pValue->ToBoolean(context).ToLocalChecked()->Value();
820 }
821
822 double FXJS_ToNumber(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
823 if (pValue.IsEmpty())
824 return 0.0;
825 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
826 return pValue->ToNumber(context).ToLocalChecked()->Value();
827 }
828
829 v8::Local<v8::Object> FXJS_ToObject(v8::Isolate* pIsolate,
830 v8::Local<v8::Value> pValue) {
831 if (pValue.IsEmpty())
832 return v8::Local<v8::Object>();
833 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
834 return pValue->ToObject(context).ToLocalChecked();
835 }
836
837 CFX_WideString FXJS_ToString(v8::Isolate* pIsolate,
838 v8::Local<v8::Value> pValue) {
839 if (pValue.IsEmpty())
840 return L"";
841 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
842 v8::String::Utf8Value s(pValue->ToString(context).ToLocalChecked());
843 return CFX_WideString::FromUTF8(CFX_ByteStringC(*s, s.length()));
844 }
845
846 v8::Local<v8::Array> FXJS_ToArray(v8::Isolate* pIsolate,
847 v8::Local<v8::Value> pValue) {
848 if (pValue.IsEmpty())
849 return v8::Local<v8::Array>();
850 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
851 return v8::Local<v8::Array>::Cast(pValue->ToObject(context).ToLocalChecked());
852 }
853
854 void FXJS_ValueCopy(v8::Local<v8::Value>& pTo, v8::Local<v8::Value> pFrom) {
855 pTo = pFrom;
856 }
OLDNEW
« no previous file with comments | « fpdfsdk/javascript/cjs_runtime.h ('k') | fpdfsdk/jsapi/fxjs_v8_embeddertest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698