blob: b0fd6fbb9fa89d3eabf076f149fc2de9402f2c35 [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
7#include "../../../core/include/fxcrt/fx_basic.h"
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07008#include "../../../core/include/fxcrt/fx_ext.h"
John Abd-El-Malek5110c472014-05-17 22:33:34 -07009#include "../../include/jsapi/fxjs_v8.h"
10#include "../../include/fsdk_define.h"
11#include "time.h"
12#include <cmath>
13#include <limits>
14
Tom Sepez142165e2015-09-11 13:21:50 -070015const wchar_t kFXJSValueNameString[] = L"string";
16const wchar_t kFXJSValueNameNumber[] = L"number";
17const wchar_t kFXJSValueNameBoolean[] = L"boolean";
18const wchar_t kFXJSValueNameDate[] = L"date";
19const wchar_t kFXJSValueNameObject[] = L"object";
20const wchar_t kFXJSValueNameFxobj[] = L"fxobj";
21const wchar_t kFXJSValueNameNull[] = L"null";
22const wchar_t kFXJSValueNameUndefined[] = L"undefined";
John Abd-El-Malek5110c472014-05-17 22:33:34 -070023
Nico Weber9d8ec5a2015-08-04 13:00:21 -070024const static FX_DWORD g_nan[2] = {0, 0x7FF80000};
25static double GetNan() {
Bruce Dawson87e95982015-01-02 12:05:17 -080026 return *(double*)g_nan;
27}
Jochen Eisinger06b60022015-07-30 17:44:35 +020028static unsigned int g_embedderDataSlot = 0u;
John Abd-El-Malek5110c472014-05-17 22:33:34 -070029
Nico Weber9d8ec5a2015-08-04 13:00:21 -070030class CJS_PrivateData {
31 public:
32 CJS_PrivateData() : ObjDefID(-1), pPrivate(NULL) {}
33 int ObjDefID;
34 void* pPrivate;
John Abd-El-Malek5110c472014-05-17 22:33:34 -070035};
36
Nico Weber9d8ec5a2015-08-04 13:00:21 -070037class CJS_ObjDefintion {
38 public:
39 CJS_ObjDefintion(v8::Isolate* isolate,
40 const wchar_t* sObjName,
41 FXJSOBJTYPE eObjType,
42 LP_CONSTRUCTOR pConstructor,
43 LP_DESTRUCTOR pDestructor)
44 : objName(sObjName),
45 objType(eObjType),
46 m_pConstructor(pConstructor),
47 m_pDestructor(pDestructor),
48 m_bSetAsGlobalObject(FALSE) {
49 v8::Isolate::Scope isolate_scope(isolate);
50 v8::HandleScope handle_scope(isolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -070051
Nico Weber9d8ec5a2015-08-04 13:00:21 -070052 v8::Local<v8::ObjectTemplate> objTemplate =
53 v8::ObjectTemplate::New(isolate);
54 objTemplate->SetInternalFieldCount(2);
55 m_objTemplate.Reset(isolate, objTemplate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -070056
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057 // Document as the global object.
58 if (FXSYS_wcscmp(sObjName, L"Document") == 0) {
59 m_bSetAsGlobalObject = TRUE;
60 }
61 }
62 ~CJS_ObjDefintion() {
63 m_objTemplate.Reset();
64 m_StaticObj.Reset();
65 }
John Abd-El-Malek5110c472014-05-17 22:33:34 -070066
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067 public:
68 const wchar_t* objName;
69 FXJSOBJTYPE objType;
70 LP_CONSTRUCTOR m_pConstructor;
71 LP_DESTRUCTOR m_pDestructor;
72 FX_BOOL m_bSetAsGlobalObject;
John Abd-El-Malek5110c472014-05-17 22:33:34 -070073
Nico Weber9d8ec5a2015-08-04 13:00:21 -070074 v8::Global<v8::ObjectTemplate> m_objTemplate;
75 v8::Global<v8::Object> m_StaticObj;
John Abd-El-Malek5110c472014-05-17 22:33:34 -070076};
77
Tom Sepez808a99e2015-09-10 12:28:37 -070078int JS_DefineObj(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -070079 const wchar_t* sObjName,
80 FXJSOBJTYPE eObjType,
81 LP_CONSTRUCTOR pConstructor,
82 LP_DESTRUCTOR pDestructor) {
Tom Sepez808a99e2015-09-10 12:28:37 -070083 v8::Isolate::Scope isolate_scope(pIsolate);
84 v8::HandleScope handle_scope(pIsolate);
85 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 if (!pArray) {
Tom Sepezae51c812015-08-05 12:34:06 -070087 pArray = new CFX_PtrArray();
Tom Sepez808a99e2015-09-10 12:28:37 -070088 pIsolate->SetData(g_embedderDataSlot, pArray);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070089 }
Tom Sepez808a99e2015-09-10 12:28:37 -070090 CJS_ObjDefintion* pObjDef = new CJS_ObjDefintion(pIsolate, sObjName, eObjType,
Nico Weber077f1a32015-08-06 15:08:57 -070091 pConstructor, pDestructor);
Nico Weber9d8ec5a2015-08-04 13:00:21 -070092 pArray->Add(pObjDef);
93 return pArray->GetSize() - 1;
John Abd-El-Malek5110c472014-05-17 22:33:34 -070094}
95
Tom Sepez142165e2015-09-11 13:21:50 -070096void JS_DefineObjMethod(v8::Isolate* pIsolate,
97 int nObjDefnID,
98 const wchar_t* sMethodName,
99 v8::FunctionCallback pMethodCall) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700100 v8::Isolate::Scope isolate_scope(pIsolate);
101 v8::HandleScope handle_scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700102
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700103 CFX_WideString ws = CFX_WideString(sMethodName);
104 CFX_ByteString bsMethodName = ws.UTF8Encode();
Tom Sepez808a99e2015-09-10 12:28:37 -0700105 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700106
Tom Sepez142165e2015-09-11 13:21:50 -0700107 // Note: GetAt() halts if out-of-range even in release builds.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700108 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID);
109 v8::Local<v8::ObjectTemplate> objTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700110 v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
111 objTemp->Set(
112 v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
113 v8::NewStringType::kNormal).ToLocalChecked(),
114 v8::FunctionTemplate::New(pIsolate, pMethodCall), v8::ReadOnly);
115 pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700116}
117
Tom Sepez142165e2015-09-11 13:21:50 -0700118void JS_DefineObjProperty(v8::Isolate* pIsolate,
119 int nObjDefnID,
120 const wchar_t* sPropName,
121 v8::AccessorGetterCallback pPropGet,
122 v8::AccessorSetterCallback pPropPut) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700123 v8::Isolate::Scope isolate_scope(pIsolate);
124 v8::HandleScope handle_scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700125
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700126 CFX_WideString ws = CFX_WideString(sPropName);
127 CFX_ByteString bsPropertyName = ws.UTF8Encode();
Tom Sepez808a99e2015-09-10 12:28:37 -0700128 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700129
Tom Sepez142165e2015-09-11 13:21:50 -0700130 // Note: GetAt() halts if out-of-range even in release builds.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID);
132 v8::Local<v8::ObjectTemplate> objTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700133 v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
134 objTemp->SetAccessor(
135 v8::String::NewFromUtf8(pIsolate, bsPropertyName.c_str(),
136 v8::NewStringType::kNormal).ToLocalChecked(),
137 pPropGet, pPropPut);
138 pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700139}
140
Tom Sepez142165e2015-09-11 13:21:50 -0700141void JS_DefineObjAllProperties(v8::Isolate* pIsolate,
142 int nObjDefnID,
143 v8::NamedPropertyQueryCallback pPropQurey,
144 v8::NamedPropertyGetterCallback pPropGet,
145 v8::NamedPropertySetterCallback pPropPut,
146 v8::NamedPropertyDeleterCallback pPropDel) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700147 v8::Isolate::Scope isolate_scope(pIsolate);
148 v8::HandleScope handle_scope(pIsolate);
Tom Sepez808a99e2015-09-10 12:28:37 -0700149 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700150
Tom Sepez142165e2015-09-11 13:21:50 -0700151 // Note: GetAt() halts if out-of-range even in release builds.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700152 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID);
153 v8::Local<v8::ObjectTemplate> objTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700154 v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700155 objTemp->SetNamedPropertyHandler(pPropGet, pPropPut, pPropQurey, pPropDel);
Tom Sepez808a99e2015-09-10 12:28:37 -0700156 pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700157}
158
Tom Sepez142165e2015-09-11 13:21:50 -0700159void JS_DefineObjConst(v8::Isolate* pIsolate,
160 int nObjDefnID,
161 const wchar_t* sConstName,
162 v8::Local<v8::Value> pDefault) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700163 v8::Isolate::Scope isolate_scope(pIsolate);
164 v8::HandleScope handle_scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700165
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700166 CFX_WideString ws = CFX_WideString(sConstName);
167 CFX_ByteString bsConstName = ws.UTF8Encode();
Tom Sepez142165e2015-09-11 13:21:50 -0700168 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700169
Tom Sepez142165e2015-09-11 13:21:50 -0700170 // Note: GetAt() halts if out-of-range even in release builds.
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700171 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID);
172 v8::Local<v8::ObjectTemplate> objTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700173 v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
174 objTemp->Set(pIsolate, bsConstName.c_str(), pDefault);
175 pObjDef->m_objTemplate.Reset(pIsolate, objTemp);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700176}
177
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178static v8::Global<v8::ObjectTemplate>& _getGlobalObjectTemplate(
Tom Sepez808a99e2015-09-10 12:28:37 -0700179 v8::Isolate* pIsolate) {
180 v8::Isolate::Scope isolate_scope(pIsolate);
181 v8::HandleScope handle_scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700182
Tom Sepez808a99e2015-09-10 12:28:37 -0700183 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700184 ASSERT(pArray != NULL);
185 for (int i = 0; i < pArray->GetSize(); i++) {
186 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(i);
187 if (pObjDef->m_bSetAsGlobalObject)
188 return pObjDef->m_objTemplate;
189 }
190 static v8::Global<v8::ObjectTemplate> gloabalObjectTemplate;
191 return gloabalObjectTemplate;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700192}
193
Tom Sepez142165e2015-09-11 13:21:50 -0700194void JS_DefineGlobalMethod(v8::Isolate* pIsolate,
195 const wchar_t* sMethodName,
196 v8::FunctionCallback pMethodCall) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700197 v8::Isolate::Scope isolate_scope(pIsolate);
198 v8::HandleScope handle_scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700199
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700200 CFX_WideString ws = CFX_WideString(sMethodName);
201 CFX_ByteString bsMethodName = ws.UTF8Encode();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700202
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 v8::Local<v8::FunctionTemplate> funTempl =
Tom Sepez808a99e2015-09-10 12:28:37 -0700204 v8::FunctionTemplate::New(pIsolate, pMethodCall);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700205 v8::Local<v8::ObjectTemplate> objTemp;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700206
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207 v8::Global<v8::ObjectTemplate>& globalObjTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700208 _getGlobalObjectTemplate(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209 if (globalObjTemp.IsEmpty())
Tom Sepez808a99e2015-09-10 12:28:37 -0700210 objTemp = v8::ObjectTemplate::New(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700211 else
Tom Sepez808a99e2015-09-10 12:28:37 -0700212 objTemp = v8::Local<v8::ObjectTemplate>::New(pIsolate, globalObjTemp);
213 objTemp->Set(
214 v8::String::NewFromUtf8(pIsolate, bsMethodName.c_str(),
215 v8::NewStringType::kNormal).ToLocalChecked(),
216 funTempl, v8::ReadOnly);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700217
Tom Sepez808a99e2015-09-10 12:28:37 -0700218 globalObjTemp.Reset(pIsolate, objTemp);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700219}
220
Tom Sepez142165e2015-09-11 13:21:50 -0700221void JS_DefineGlobalConst(v8::Isolate* pIsolate,
222 const wchar_t* sConstName,
223 v8::Local<v8::Value> pDefault) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700224 v8::Isolate::Scope isolate_scope(pIsolate);
225 v8::HandleScope handle_scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700226
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227 CFX_WideString ws = CFX_WideString(sConstName);
228 CFX_ByteString bsConst = ws.UTF8Encode();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700229
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 v8::Local<v8::ObjectTemplate> objTemp;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700231
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232 v8::Global<v8::ObjectTemplate>& globalObjTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700233 _getGlobalObjectTemplate(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700234 if (globalObjTemp.IsEmpty())
Tom Sepez808a99e2015-09-10 12:28:37 -0700235 objTemp = v8::ObjectTemplate::New(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700236 else
Tom Sepez808a99e2015-09-10 12:28:37 -0700237 objTemp = v8::Local<v8::ObjectTemplate>::New(pIsolate, globalObjTemp);
238 objTemp->Set(
239 v8::String::NewFromUtf8(pIsolate, bsConst.c_str(),
240 v8::NewStringType::kNormal).ToLocalChecked(),
241 pDefault, v8::ReadOnly);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700242
Tom Sepez808a99e2015-09-10 12:28:37 -0700243 globalObjTemp.Reset(pIsolate, objTemp);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700244}
245
Tom Sepez808a99e2015-09-10 12:28:37 -0700246void JS_InitialRuntime(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700247 IFXJS_Runtime* pFXRuntime,
248 IFXJS_Context* context,
249 v8::Global<v8::Context>& v8PersistentContext) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700250 v8::Isolate::Scope isolate_scope(pIsolate);
251 v8::Locker locker(pIsolate);
252 v8::HandleScope handle_scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700253
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700254 v8::Global<v8::ObjectTemplate>& globalObjTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700255 _getGlobalObjectTemplate(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256 v8::Local<v8::Context> v8Context = v8::Context::New(
Tom Sepez808a99e2015-09-10 12:28:37 -0700257 pIsolate, NULL,
258 v8::Local<v8::ObjectTemplate>::New(pIsolate, globalObjTemp));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 v8::Context::Scope context_scope(v8Context);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700260
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261 // v8::Local<External> ptr = External::New(isolate, pFXRuntime);
262 // v8Context->SetEmbedderData(1, ptr);
263 // TODO(tsepez): Don't use more than one embedder data slot.
Tom Sepez808a99e2015-09-10 12:28:37 -0700264 pIsolate->SetData(2, pFXRuntime);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700265
Tom Sepez808a99e2015-09-10 12:28:37 -0700266 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700267 if (!pArray)
268 return;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700269
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700270 for (int i = 0; i < pArray->GetSize(); i++) {
271 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(i);
272 CFX_WideString ws = CFX_WideString(pObjDef->objName);
273 CFX_ByteString bs = ws.UTF8Encode();
274 v8::Local<v8::String> objName =
Tom Sepez808a99e2015-09-10 12:28:37 -0700275 v8::String::NewFromUtf8(pIsolate, bs.c_str(),
276 v8::NewStringType::kNormal,
277 bs.GetLength()).ToLocalChecked();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700278
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700279 if (pObjDef->objType == JS_DYNAMIC) {
280 // Document is set as global object, need to construct it first.
281 CFX_WideString wsString(L"Document");
282 if (ws.Equal(wsString)) {
Tom Sepezae51c812015-08-05 12:34:06 -0700283 CJS_PrivateData* pPrivateData = new CJS_PrivateData;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700284 pPrivateData->ObjDefID = i;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700285
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700286 v8Context->Global()
287 ->GetPrototype()
288 ->ToObject(v8Context)
289 .ToLocalChecked()
290 ->SetAlignedPointerInInternalField(0, pPrivateData);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700291
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700292 if (pObjDef->m_pConstructor)
293 pObjDef->m_pConstructor(context, v8Context->Global()
294 ->GetPrototype()
295 ->ToObject(v8Context)
296 .ToLocalChecked(),
297 v8Context->Global()
298 ->GetPrototype()
299 ->ToObject(v8Context)
300 .ToLocalChecked());
301 }
302 } else {
Tom Sepez808a99e2015-09-10 12:28:37 -0700303 v8::Local<v8::Object> obj = JS_NewFxDynamicObj(pIsolate, context, i);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304 v8Context->Global()->Set(v8Context, objName, obj).FromJust();
Tom Sepez808a99e2015-09-10 12:28:37 -0700305 pObjDef->m_StaticObj.Reset(pIsolate, obj);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700306 }
307 }
Tom Sepez808a99e2015-09-10 12:28:37 -0700308 v8PersistentContext.Reset(pIsolate, v8Context);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700309}
310
Tom Sepez808a99e2015-09-10 12:28:37 -0700311void JS_ReleaseRuntime(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700312 v8::Global<v8::Context>& v8PersistentContext) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700313 v8::Isolate::Scope isolate_scope(pIsolate);
314 v8::Locker locker(pIsolate);
315 v8::HandleScope handle_scope(pIsolate);
316 v8::Local<v8::Context> context =
317 v8::Local<v8::Context>::New(pIsolate, v8PersistentContext);
318 v8::Context::Scope context_scope(context);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700319
Tom Sepez808a99e2015-09-10 12:28:37 -0700320 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700321 if (!pArray)
322 return;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700323
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700324 for (int i = 0; i < pArray->GetSize(); i++) {
325 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(i);
326 if (!pObjDef->m_StaticObj.IsEmpty()) {
327 v8::Local<v8::Object> pObj =
Tom Sepez808a99e2015-09-10 12:28:37 -0700328 v8::Local<v8::Object>::New(pIsolate, pObjDef->m_StaticObj);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329 if (pObjDef->m_pDestructor)
330 pObjDef->m_pDestructor(pObj);
331 JS_FreePrivate(pObj);
332 }
333 delete pObjDef;
334 }
335 delete pArray;
Tom Sepez808a99e2015-09-10 12:28:37 -0700336
337 pIsolate->SetData(1, NULL);
338 pIsolate->SetData(g_embedderDataSlot, NULL);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700339 // TODO(tsepez): Don't use more than one embedder data slot.
Tom Sepez808a99e2015-09-10 12:28:37 -0700340 pIsolate->SetData(2, NULL);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700341}
342
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700343void JS_Initial(unsigned int embedderDataSlot) {
344 g_embedderDataSlot = embedderDataSlot;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700345}
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700346
Tom Sepez9ed941a2015-09-01 09:51:10 -0700347void JS_Release() {
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700348}
349
Tom Sepez808a99e2015-09-10 12:28:37 -0700350int JS_Execute(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700351 IFXJS_Context* pJSContext,
352 const wchar_t* script,
353 long length,
354 FXJSErr* perror) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700355 v8::Isolate::Scope isolate_scope(pIsolate);
356 v8::TryCatch try_catch(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700357
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700358 CFX_WideString wsScript(script);
359 CFX_ByteString bsScript = wsScript.UTF8Encode();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700360
Tom Sepez808a99e2015-09-10 12:28:37 -0700361 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700362 v8::Local<v8::Script> compiled_script;
Tom Sepez808a99e2015-09-10 12:28:37 -0700363 if (!v8::Script::Compile(
364 context, v8::String::NewFromUtf8(
365 pIsolate, bsScript.c_str(), v8::NewStringType::kNormal,
366 bsScript.GetLength()).ToLocalChecked())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700367 .ToLocal(&compiled_script)) {
368 v8::String::Utf8Value error(try_catch.Exception());
369 return -1;
370 }
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700371
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700372 v8::Local<v8::Value> result;
373 if (!compiled_script->Run(context).ToLocal(&result)) {
374 v8::String::Utf8Value error(try_catch.Exception());
375 return -1;
376 }
377 return 0;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700378}
379
Tom Sepez808a99e2015-09-10 12:28:37 -0700380v8::Local<v8::Object> JS_NewFxDynamicObj(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700381 IFXJS_Context* pJSContext,
382 int nObjDefnID) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700383 v8::Isolate::Scope isolate_scope(pIsolate);
384 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700385 if (-1 == nObjDefnID) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700386 v8::Local<v8::ObjectTemplate> objTempl = v8::ObjectTemplate::New(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700387 v8::Local<v8::Object> obj;
388 if (objTempl->NewInstance(context).ToLocal(&obj))
389 return obj;
390 return v8::Local<v8::Object>();
391 }
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700392
Tom Sepez808a99e2015-09-10 12:28:37 -0700393 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700394 if (!pArray)
395 return v8::Local<v8::Object>();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700396
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700397 if (nObjDefnID < 0 || nObjDefnID >= pArray->GetSize())
398 return v8::Local<v8::Object>();
399 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700400
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700401 v8::Local<v8::ObjectTemplate> objTemp =
Tom Sepez808a99e2015-09-10 12:28:37 -0700402 v8::Local<v8::ObjectTemplate>::New(pIsolate, pObjDef->m_objTemplate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700403 v8::Local<v8::Object> obj;
404 if (!objTemp->NewInstance(context).ToLocal(&obj))
405 return v8::Local<v8::Object>();
Tom Sepezae51c812015-08-05 12:34:06 -0700406 CJS_PrivateData* pPrivateData = new CJS_PrivateData;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700407 pPrivateData->ObjDefID = nObjDefnID;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700408
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700409 obj->SetAlignedPointerInInternalField(0, pPrivateData);
410 if (pObjDef->m_pConstructor)
411 pObjDef->m_pConstructor(
412 pJSContext, obj,
413 context->Global()->GetPrototype()->ToObject(context).ToLocalChecked());
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700414
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700415 return obj;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700416}
417
Tom Sepez808a99e2015-09-10 12:28:37 -0700418v8::Local<v8::Object> JS_GetStaticObj(v8::Isolate* pIsolate, int nObjDefnID) {
419 v8::Isolate::Scope isolate_scope(pIsolate);
420 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 if (!pArray)
422 return v8::Local<v8::Object>();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700423
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700424 if (nObjDefnID < 0 || nObjDefnID >= pArray->GetSize())
425 return v8::Local<v8::Object>();
426 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(nObjDefnID);
427 v8::Local<v8::Object> obj =
Tom Sepez808a99e2015-09-10 12:28:37 -0700428 v8::Local<v8::Object>::New(pIsolate, pObjDef->m_StaticObj);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429 return obj;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700430}
431
Tom Sepez808a99e2015-09-10 12:28:37 -0700432v8::Local<v8::Object> JS_GetThisObj(v8::Isolate* pIsolate) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700433 // Return the global object.
Tom Sepez808a99e2015-09-10 12:28:37 -0700434 v8::Isolate::Scope isolate_scope(pIsolate);
435 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 if (!pArray)
437 return v8::Local<v8::Object>();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700438
Tom Sepez808a99e2015-09-10 12:28:37 -0700439 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700440 return context->Global()->GetPrototype()->ToObject(context).ToLocalChecked();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700441}
442
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700443int JS_GetObjDefnID(v8::Local<v8::Object> pObj) {
444 if (pObj.IsEmpty() || !pObj->InternalFieldCount())
445 return -1;
446 CJS_PrivateData* pPrivateData =
447 (CJS_PrivateData*)pObj->GetAlignedPointerFromInternalField(0);
448 if (pPrivateData)
449 return pPrivateData->ObjDefID;
450 return -1;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700451}
452
Tom Sepez808a99e2015-09-10 12:28:37 -0700453v8::Isolate* JS_GetRuntime(v8::Local<v8::Object> pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700454 if (pObj.IsEmpty())
455 return NULL;
456 v8::Local<v8::Context> context = pObj->CreationContext();
457 if (context.IsEmpty())
458 return NULL;
459 return context->GetIsolate();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700460}
461
Tom Sepez808a99e2015-09-10 12:28:37 -0700462int JS_GetObjDefnID(v8::Isolate* pIsolate, const wchar_t* pObjName) {
463 v8::Isolate::Scope isolate_scope(pIsolate);
464 CFX_PtrArray* pArray = (CFX_PtrArray*)pIsolate->GetData(g_embedderDataSlot);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700465 if (!pArray)
466 return -1;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700467
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468 for (int i = 0; i < pArray->GetSize(); i++) {
469 CJS_ObjDefintion* pObjDef = (CJS_ObjDefintion*)pArray->GetAt(i);
470 if (FXSYS_wcscmp(pObjDef->objName, pObjName) == 0)
471 return i;
472 }
473 return -1;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700474}
475
Tom Sepez808a99e2015-09-10 12:28:37 -0700476void JS_Error(v8::Isolate* pIsolate, const CFX_WideString& message) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700477 // Conversion from pdfium's wchar_t wide-strings to v8's uint16_t
478 // wide-strings isn't handled by v8, so use UTF8 as a common
479 // intermediate format.
480 CFX_ByteString utf8_message = message.UTF8Encode();
Tom Sepez808a99e2015-09-10 12:28:37 -0700481 pIsolate->ThrowException(
482 v8::String::NewFromUtf8(pIsolate, utf8_message.c_str(),
483 v8::NewStringType::kNormal).ToLocalChecked());
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700484}
485
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700486unsigned JS_CalcHash(const wchar_t* main, unsigned nLen) {
487 return (unsigned)FX_HashCode_String_GetW((const FX_WCHAR*)main, nLen);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700488}
489
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490unsigned JS_CalcHash(const wchar_t* main) {
491 return (unsigned)FX_HashCode_String_GetW((const FX_WCHAR*)main,
492 FXSYS_wcslen(main));
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700493}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700494const wchar_t* JS_GetTypeof(v8::Local<v8::Value> pObj) {
495 if (pObj.IsEmpty())
496 return NULL;
497 if (pObj->IsString())
Tom Sepez142165e2015-09-11 13:21:50 -0700498 return kFXJSValueNameString;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700499 if (pObj->IsNumber())
Tom Sepez142165e2015-09-11 13:21:50 -0700500 return kFXJSValueNameNumber;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700501 if (pObj->IsBoolean())
Tom Sepez142165e2015-09-11 13:21:50 -0700502 return kFXJSValueNameBoolean;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700503 if (pObj->IsDate())
Tom Sepez142165e2015-09-11 13:21:50 -0700504 return kFXJSValueNameDate;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505 if (pObj->IsObject())
Tom Sepez142165e2015-09-11 13:21:50 -0700506 return kFXJSValueNameObject;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700507 if (pObj->IsNull())
Tom Sepez142165e2015-09-11 13:21:50 -0700508 return kFXJSValueNameNull;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700509 if (pObj->IsUndefined())
Tom Sepez142165e2015-09-11 13:21:50 -0700510 return kFXJSValueNameUndefined;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700511 return NULL;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700512}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700513void JS_SetPrivate(v8::Local<v8::Object> pObj, void* p) {
514 JS_SetPrivate(NULL, pObj, p);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700515}
516
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700517void* JS_GetPrivate(v8::Local<v8::Object> pObj) {
518 return JS_GetPrivate(NULL, pObj);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700519}
520
Tom Sepez808a99e2015-09-10 12:28:37 -0700521void JS_SetPrivate(v8::Isolate* pIsolate, v8::Local<v8::Object> pObj, void* p) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522 if (pObj.IsEmpty() || !pObj->InternalFieldCount())
523 return;
524 CJS_PrivateData* pPrivateData =
525 (CJS_PrivateData*)pObj->GetAlignedPointerFromInternalField(0);
526 if (!pPrivateData)
527 return;
528 pPrivateData->pPrivate = p;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700529}
530
Tom Sepez808a99e2015-09-10 12:28:37 -0700531void* JS_GetPrivate(v8::Isolate* pIsolate, v8::Local<v8::Object> pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700532 if (pObj.IsEmpty())
533 return NULL;
534 CJS_PrivateData* pPrivateData = NULL;
535 if (pObj->InternalFieldCount())
536 pPrivateData =
537 (CJS_PrivateData*)pObj->GetAlignedPointerFromInternalField(0);
538 else {
539 // It could be a global proxy object.
540 v8::Local<v8::Value> v = pObj->GetPrototype();
Tom Sepez808a99e2015-09-10 12:28:37 -0700541 v8::Isolate* isolate = (v8::Isolate*)pIsolate;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700542 v8::Local<v8::Context> context = isolate->GetCurrentContext();
543 if (v->IsObject())
544 pPrivateData = (CJS_PrivateData*)v->ToObject(context)
545 .ToLocalChecked()
546 ->GetAlignedPointerFromInternalField(0);
547 }
548 if (!pPrivateData)
549 return NULL;
550 return pPrivateData->pPrivate;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700551}
552
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700553void JS_FreePrivate(void* pPrivateData) {
554 delete (CJS_PrivateData*)pPrivateData;
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200555}
556
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700557void JS_FreePrivate(v8::Local<v8::Object> pObj) {
558 if (pObj.IsEmpty() || !pObj->InternalFieldCount())
559 return;
560 JS_FreePrivate(pObj->GetAlignedPointerFromInternalField(0));
561 pObj->SetAlignedPointerInInternalField(0, NULL);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700562}
563
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700564v8::Local<v8::Value> JS_GetObjectValue(v8::Local<v8::Object> pObj) {
565 return pObj;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700566}
567
Tom Sepez808a99e2015-09-10 12:28:37 -0700568v8::Local<v8::String> WSToJSString(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700569 const wchar_t* PropertyName,
570 int Len = -1) {
571 CFX_WideString ws = CFX_WideString(PropertyName, Len);
572 CFX_ByteString bs = ws.UTF8Encode();
Tom Sepez808a99e2015-09-10 12:28:37 -0700573 if (!pIsolate)
574 pIsolate = v8::Isolate::GetCurrent();
575 return v8::String::NewFromUtf8(pIsolate, bs.c_str(),
576 v8::NewStringType::kNormal).ToLocalChecked();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700577}
578
Tom Sepez808a99e2015-09-10 12:28:37 -0700579v8::Local<v8::Value> JS_GetObjectElement(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700580 v8::Local<v8::Object> pObj,
581 const wchar_t* PropertyName) {
582 if (pObj.IsEmpty())
583 return v8::Local<v8::Value>();
584 v8::Local<v8::Value> val;
Tom Sepez808a99e2015-09-10 12:28:37 -0700585 if (!pObj->Get(pIsolate->GetCurrentContext(),
586 WSToJSString(pIsolate, PropertyName)).ToLocal(&val))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700587 return v8::Local<v8::Value>();
588 return val;
589}
590
Tom Sepez808a99e2015-09-10 12:28:37 -0700591v8::Local<v8::Array> JS_GetObjectElementNames(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700592 v8::Local<v8::Object> pObj) {
593 if (pObj.IsEmpty())
594 return v8::Local<v8::Array>();
595 v8::Local<v8::Array> val;
Tom Sepez808a99e2015-09-10 12:28:37 -0700596 if (!pObj->GetPropertyNames(pIsolate->GetCurrentContext()).ToLocal(&val))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700597 return v8::Local<v8::Array>();
598 return val;
599}
600
Tom Sepez808a99e2015-09-10 12:28:37 -0700601void JS_PutObjectString(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700602 v8::Local<v8::Object> pObj,
603 const wchar_t* PropertyName,
604 const wchar_t* sValue) // VT_string
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700605{
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700606 if (pObj.IsEmpty())
607 return;
Tom Sepez808a99e2015-09-10 12:28:37 -0700608 pObj->Set(pIsolate->GetCurrentContext(), WSToJSString(pIsolate, PropertyName),
609 WSToJSString(pIsolate, sValue)).FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700610}
611
Tom Sepez808a99e2015-09-10 12:28:37 -0700612void JS_PutObjectNumber(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700613 v8::Local<v8::Object> pObj,
614 const wchar_t* PropertyName,
615 int nValue) {
616 if (pObj.IsEmpty())
617 return;
Tom Sepez808a99e2015-09-10 12:28:37 -0700618 pObj->Set(pIsolate->GetCurrentContext(), WSToJSString(pIsolate, PropertyName),
619 v8::Int32::New(pIsolate, nValue)).FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700620}
621
Tom Sepez808a99e2015-09-10 12:28:37 -0700622void JS_PutObjectNumber(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700623 v8::Local<v8::Object> pObj,
624 const wchar_t* PropertyName,
625 float fValue) {
626 if (pObj.IsEmpty())
627 return;
Tom Sepez808a99e2015-09-10 12:28:37 -0700628 pObj->Set(pIsolate->GetCurrentContext(), WSToJSString(pIsolate, PropertyName),
629 v8::Number::New(pIsolate, (double)fValue)).FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700630}
631
Tom Sepez808a99e2015-09-10 12:28:37 -0700632void JS_PutObjectNumber(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700633 v8::Local<v8::Object> pObj,
634 const wchar_t* PropertyName,
635 double dValue) {
636 if (pObj.IsEmpty())
637 return;
Tom Sepez808a99e2015-09-10 12:28:37 -0700638 pObj->Set(pIsolate->GetCurrentContext(), WSToJSString(pIsolate, PropertyName),
639 v8::Number::New(pIsolate, (double)dValue)).FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700640}
641
Tom Sepez808a99e2015-09-10 12:28:37 -0700642void JS_PutObjectBoolean(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700643 v8::Local<v8::Object> pObj,
644 const wchar_t* PropertyName,
645 bool bValue) {
646 if (pObj.IsEmpty())
647 return;
Tom Sepez808a99e2015-09-10 12:28:37 -0700648 pObj->Set(pIsolate->GetCurrentContext(), WSToJSString(pIsolate, PropertyName),
649 v8::Boolean::New(pIsolate, bValue)).FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700650}
651
Tom Sepez808a99e2015-09-10 12:28:37 -0700652void JS_PutObjectObject(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700653 v8::Local<v8::Object> pObj,
654 const wchar_t* PropertyName,
655 v8::Local<v8::Object> pPut) {
656 if (pObj.IsEmpty())
657 return;
Tom Sepez808a99e2015-09-10 12:28:37 -0700658 pObj->Set(pIsolate->GetCurrentContext(), WSToJSString(pIsolate, PropertyName),
659 pPut).FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700660}
661
Tom Sepez808a99e2015-09-10 12:28:37 -0700662void JS_PutObjectNull(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700663 v8::Local<v8::Object> pObj,
664 const wchar_t* PropertyName) {
665 if (pObj.IsEmpty())
666 return;
Tom Sepez808a99e2015-09-10 12:28:37 -0700667 pObj->Set(pIsolate->GetCurrentContext(), WSToJSString(pIsolate, PropertyName),
668 v8::Local<v8::Object>()).FromJust();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700669}
670
Tom Sepez808a99e2015-09-10 12:28:37 -0700671v8::Local<v8::Array> JS_NewArray(v8::Isolate* pIsolate) {
672 return v8::Array::New(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700673}
674
Tom Sepez808a99e2015-09-10 12:28:37 -0700675unsigned JS_PutArrayElement(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700676 v8::Local<v8::Array> pArray,
677 unsigned index,
678 v8::Local<v8::Value> pValue,
679 FXJSVALUETYPE eType) {
680 if (pArray.IsEmpty())
681 return 0;
Tom Sepez808a99e2015-09-10 12:28:37 -0700682 if (pArray->Set(pIsolate->GetCurrentContext(), index, pValue).IsNothing())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700683 return 0;
684 return 1;
685}
686
Tom Sepez808a99e2015-09-10 12:28:37 -0700687v8::Local<v8::Value> JS_GetArrayElement(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700688 v8::Local<v8::Array> pArray,
689 unsigned index) {
690 if (pArray.IsEmpty())
691 return v8::Local<v8::Value>();
692 v8::Local<v8::Value> val;
Tom Sepez808a99e2015-09-10 12:28:37 -0700693 if (!pArray->Get(pIsolate->GetCurrentContext(), index).ToLocal(&val))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700694 return v8::Local<v8::Value>();
695 return val;
696}
697
698unsigned JS_GetArrayLength(v8::Local<v8::Array> pArray) {
699 if (pArray.IsEmpty())
700 return 0;
701 return pArray->Length();
702}
703
Tom Sepez808a99e2015-09-10 12:28:37 -0700704v8::Local<v8::Value> JS_NewNumber(v8::Isolate* pIsolate, int number) {
705 return v8::Int32::New(pIsolate, number);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700706}
707
Tom Sepez808a99e2015-09-10 12:28:37 -0700708v8::Local<v8::Value> JS_NewNumber(v8::Isolate* pIsolate, double number) {
709 return v8::Number::New(pIsolate, number);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700710}
711
Tom Sepez808a99e2015-09-10 12:28:37 -0700712v8::Local<v8::Value> JS_NewNumber(v8::Isolate* pIsolate, float number) {
713 return v8::Number::New(pIsolate, (float)number);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700714}
715
Tom Sepez808a99e2015-09-10 12:28:37 -0700716v8::Local<v8::Value> JS_NewBoolean(v8::Isolate* pIsolate, bool b) {
717 return v8::Boolean::New(pIsolate, b);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700718}
719
Tom Sepez808a99e2015-09-10 12:28:37 -0700720v8::Local<v8::Value> JS_NewObject(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700721 v8::Local<v8::Object> pObj) {
722 if (pObj.IsEmpty())
723 return v8::Local<v8::Value>();
724 return pObj->Clone();
725}
726
Tom Sepez808a99e2015-09-10 12:28:37 -0700727v8::Local<v8::Value> JS_NewObject2(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700728 v8::Local<v8::Array> pObj) {
729 if (pObj.IsEmpty())
730 return v8::Local<v8::Value>();
731 return pObj->Clone();
732}
733
Tom Sepez808a99e2015-09-10 12:28:37 -0700734v8::Local<v8::Value> JS_NewString(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700735 const wchar_t* string) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700736 return WSToJSString(pIsolate, string);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700737}
738
Tom Sepez808a99e2015-09-10 12:28:37 -0700739v8::Local<v8::Value> JS_NewString(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700740 const wchar_t* string,
741 unsigned nLen) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700742 return WSToJSString(pIsolate, string, nLen);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700743}
744
745v8::Local<v8::Value> JS_NewNull() {
746 return v8::Local<v8::Value>();
747}
748
Tom Sepez808a99e2015-09-10 12:28:37 -0700749v8::Local<v8::Value> JS_NewDate(v8::Isolate* pIsolate, double d) {
750 return v8::Date::New(pIsolate->GetCurrentContext(), d).ToLocalChecked();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700751}
752
Tom Sepez808a99e2015-09-10 12:28:37 -0700753v8::Local<v8::Value> JS_NewValue(v8::Isolate* pIsolate) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700754 return v8::Local<v8::Value>();
755}
756
Tom Sepez808a99e2015-09-10 12:28:37 -0700757v8::Local<v8::Value> JS_GetListValue(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700758 v8::Local<v8::Value> pList,
759 int index) {
Tom Sepez808a99e2015-09-10 12:28:37 -0700760 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700761 if (!pList.IsEmpty() && pList->IsObject()) {
762 v8::Local<v8::Object> obj;
763 if (pList->ToObject(context).ToLocal(&obj)) {
764 v8::Local<v8::Value> val;
765 if (obj->Get(context, index).ToLocal(&val))
Jochen Eisingerdfa2c992015-05-19 00:38:00 +0200766 return val;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700767 }
768 }
769 return v8::Local<v8::Value>();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700770}
771
Tom Sepez808a99e2015-09-10 12:28:37 -0700772int JS_ToInt32(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700773 if (pValue.IsEmpty())
774 return 0;
Tom Sepez808a99e2015-09-10 12:28:37 -0700775 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700776 return pValue->ToInt32(context).ToLocalChecked()->Value();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700777}
778
Tom Sepez808a99e2015-09-10 12:28:37 -0700779bool JS_ToBoolean(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700780 if (pValue.IsEmpty())
781 return false;
Tom Sepez808a99e2015-09-10 12:28:37 -0700782 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700783 return pValue->ToBoolean(context).ToLocalChecked()->Value();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700784}
785
Tom Sepez808a99e2015-09-10 12:28:37 -0700786double JS_ToNumber(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700787 if (pValue.IsEmpty())
788 return 0.0;
Tom Sepez808a99e2015-09-10 12:28:37 -0700789 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700790 return pValue->ToNumber(context).ToLocalChecked()->Value();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700791}
792
Tom Sepez808a99e2015-09-10 12:28:37 -0700793v8::Local<v8::Object> JS_ToObject(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700794 v8::Local<v8::Value> pValue) {
795 if (pValue.IsEmpty())
796 return v8::Local<v8::Object>();
Tom Sepez808a99e2015-09-10 12:28:37 -0700797 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700798 return pValue->ToObject(context).ToLocalChecked();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700799}
800
Tom Sepez808a99e2015-09-10 12:28:37 -0700801CFX_WideString JS_ToString(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700802 if (pValue.IsEmpty())
803 return L"";
Tom Sepez808a99e2015-09-10 12:28:37 -0700804 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700805 v8::String::Utf8Value s(pValue->ToString(context).ToLocalChecked());
806 return CFX_WideString::FromUTF8(*s, s.length());
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700807}
808
Tom Sepez808a99e2015-09-10 12:28:37 -0700809v8::Local<v8::Array> JS_ToArray(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700810 v8::Local<v8::Value> pValue) {
811 if (pValue.IsEmpty())
812 return v8::Local<v8::Array>();
Tom Sepez808a99e2015-09-10 12:28:37 -0700813 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700814 return v8::Local<v8::Array>::Cast(pValue->ToObject(context).ToLocalChecked());
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700815}
816
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700817void JS_ValueCopy(v8::Local<v8::Value>& pTo, v8::Local<v8::Value> pFrom) {
818 pTo = pFrom;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700819}
820
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700821// JavaScript time implement begin.
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700822
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700823double _getLocalTZA() {
824 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
825 return 0;
826 time_t t = 0;
827 time(&t);
828 localtime(&t);
Bruce Dawson06e015f2015-04-09 11:10:17 -0700829#if _MSC_VER >= 1900
830 // In gcc and in Visual Studio prior to VS 2015 'timezone' is a global
831 // variable declared in time.h. That variable was deprecated and in VS 2015
832 // is removed, with _get_timezone replacing it.
833 long timezone = 0;
834 _get_timezone(&timezone);
835#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700836 return (double)(-(timezone * 1000));
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700837}
838
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700839int _getDaylightSavingTA(double d) {
840 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
841 return 0;
842 time_t t = (time_t)(d / 1000);
843 struct tm* tmp = localtime(&t);
844 if (tmp == NULL)
845 return 0;
846 if (tmp->tm_isdst > 0)
847 // One hour.
848 return (int)60 * 60 * 1000;
849 return 0;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700850}
851
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700852double _Mod(double x, double y) {
853 double r = fmod(x, y);
854 if (r < 0)
855 r += y;
856 return r;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700857}
858
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700859int _isfinite(double v) {
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700860#if _MSC_VER
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700861 return ::_finite(v);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700862#else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700863 return std::fabs(v) < std::numeric_limits<double>::max();
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700864#endif
865}
866
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700867double _toInteger(double n) {
868 return (n >= 0) ? FXSYS_floor(n) : -FXSYS_floor(-n);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700869}
870
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700871bool _isLeapYear(int year) {
872 return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0));
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700873}
874
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700875int _DayFromYear(int y) {
876 return (int)(365 * (y - 1970.0) + FXSYS_floor((y - 1969.0) / 4) -
877 FXSYS_floor((y - 1901.0) / 100) +
878 FXSYS_floor((y - 1601.0) / 400));
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700879}
880
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700881double _TimeFromYear(int y) {
882 return ((double)86400000) * _DayFromYear(y);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700883}
884
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700885double _TimeFromYearMonth(int y, int m) {
886 static int daysMonth[12] = {0, 31, 59, 90, 120, 151,
887 181, 212, 243, 273, 304, 334};
888 static int leapDaysMonth[12] = {0, 31, 60, 91, 121, 152,
889 182, 213, 244, 274, 305, 335};
890 int* pMonth = daysMonth;
891 if (_isLeapYear(y))
892 pMonth = leapDaysMonth;
893 return _TimeFromYear(y) + ((double)pMonth[m]) * 86400000;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700894}
895
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700896int _Day(double t) {
897 return (int)FXSYS_floor(t / 86400000);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700898}
899
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700900int _YearFromTime(double t) {
901 // estimate the time.
902 int y = 1970 + (int)(t / (365.0 * 86400000));
903 if (_TimeFromYear(y) <= t) {
904 while (_TimeFromYear(y + 1) <= t)
905 y++;
906 } else
907 while (_TimeFromYear(y - 1) > t)
908 y--;
909 return y;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700910}
911
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700912int _DayWithinYear(double t) {
913 int year = _YearFromTime(t);
914 int day = _Day(t);
915 return day - _DayFromYear(year);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700916}
917
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700918int _MonthFromTime(double t) {
919 int day = _DayWithinYear(t);
920 int year = _YearFromTime(t);
921 if (0 <= day && day < 31)
922 return 0;
923 if (31 <= day && day < 59 + _isLeapYear(year))
924 return 1;
925 if ((59 + _isLeapYear(year)) <= day && day < (90 + _isLeapYear(year)))
926 return 2;
927 if ((90 + _isLeapYear(year)) <= day && day < (120 + _isLeapYear(year)))
928 return 3;
929 if ((120 + _isLeapYear(year)) <= day && day < (151 + _isLeapYear(year)))
930 return 4;
931 if ((151 + _isLeapYear(year)) <= day && day < (181 + _isLeapYear(year)))
932 return 5;
933 if ((181 + _isLeapYear(year)) <= day && day < (212 + _isLeapYear(year)))
934 return 6;
935 if ((212 + _isLeapYear(year)) <= day && day < (243 + _isLeapYear(year)))
936 return 7;
937 if ((243 + _isLeapYear(year)) <= day && day < (273 + _isLeapYear(year)))
938 return 8;
939 if ((273 + _isLeapYear(year)) <= day && day < (304 + _isLeapYear(year)))
940 return 9;
941 if ((304 + _isLeapYear(year)) <= day && day < (334 + _isLeapYear(year)))
942 return 10;
943 if ((334 + _isLeapYear(year)) <= day && day < (365 + _isLeapYear(year)))
944 return 11;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700945
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700946 return -1;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700947}
948
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700949int _DateFromTime(double t) {
950 int day = _DayWithinYear(t);
951 int year = _YearFromTime(t);
952 bool leap = _isLeapYear(year);
953 int month = _MonthFromTime(t);
954 switch (month) {
955 case 0:
956 return day + 1;
957 case 1:
958 return day - 30;
959 case 2:
960 return day - 58 - leap;
961 case 3:
962 return day - 89 - leap;
963 case 4:
964 return day - 119 - leap;
965 case 5:
966 return day - 150 - leap;
967 case 6:
968 return day - 180 - leap;
969 case 7:
970 return day - 211 - leap;
971 case 8:
972 return day - 242 - leap;
973 case 9:
974 return day - 272 - leap;
975 case 10:
976 return day - 303 - leap;
977 case 11:
978 return day - 333 - leap;
979 default:
980 return 0;
981 }
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700982}
983
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700984double JS_GetDateTime() {
985 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
986 return 0;
987 time_t t = time(NULL);
988 struct tm* pTm = localtime(&t);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700989
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700990 int year = pTm->tm_year + 1900;
991 double t1 = _TimeFromYear(year);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700992
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700993 return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 +
994 pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0;
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700995}
996
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700997int JS_GetYearFromTime(double dt) {
998 return _YearFromTime(dt);
John Abd-El-Malek5110c472014-05-17 22:33:34 -0700999}
1000
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001001int JS_GetMonthFromTime(double dt) {
1002 return _MonthFromTime(dt);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001003}
1004
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001005int JS_GetDayFromTime(double dt) {
1006 return _DateFromTime(dt);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001007}
1008
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001009int JS_GetHourFromTime(double dt) {
1010 return (int)_Mod(FXSYS_floor((double)(dt / (60 * 60 * 1000))), 24);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001011}
1012
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001013int JS_GetMinFromTime(double dt) {
1014 return (int)_Mod(FXSYS_floor((double)(dt / (60 * 1000))), 60);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001015}
1016
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001017int JS_GetSecFromTime(double dt) {
1018 return (int)_Mod(FXSYS_floor((double)(dt / 1000)), 60);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001019}
1020
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001021double JS_DateParse(const wchar_t* string) {
1022 v8::Isolate* pIsolate = v8::Isolate::GetCurrent();
1023 v8::Isolate::Scope isolate_scope(pIsolate);
1024 v8::HandleScope scope(pIsolate);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001025
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001026 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07001027
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001028 // Use the built-in object method.
1029 v8::Local<v8::Value> v =
1030 context->Global()
1031 ->Get(context, v8::String::NewFromUtf8(pIsolate, "Date",
1032 v8::NewStringType::kNormal)
1033 .ToLocalChecked())
1034 .ToLocalChecked();
1035 if (v->IsObject()) {
1036 v8::Local<v8::Object> o = v->ToObject(context).ToLocalChecked();
1037 v = o->Get(context, v8::String::NewFromUtf8(pIsolate, "parse",
1038 v8::NewStringType::kNormal)
1039 .ToLocalChecked())
1040 .ToLocalChecked();
1041 if (v->IsFunction()) {
1042 v8::Local<v8::Function> funC = v8::Local<v8::Function>::Cast(v);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001043
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001044 const int argc = 1;
1045 v8::Local<v8::String> timeStr = WSToJSString(pIsolate, string);
1046 v8::Local<v8::Value> argv[argc] = {timeStr};
1047 v = funC->Call(context, context->Global(), argc, argv).ToLocalChecked();
1048 if (v->IsNumber()) {
1049 double date = v->ToNumber(context).ToLocalChecked()->Value();
1050 if (!_isfinite(date))
1051 return date;
1052 return date + _getLocalTZA() + _getDaylightSavingTA(date);
1053 }
1054 }
1055 }
1056 return 0;
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001057}
1058
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001059double JS_MakeDay(int nYear, int nMonth, int nDate) {
1060 if (!_isfinite(nYear) || !_isfinite(nMonth) || !_isfinite(nDate))
1061 return GetNan();
1062 double y = _toInteger(nYear);
1063 double m = _toInteger(nMonth);
1064 double dt = _toInteger(nDate);
1065 double ym = y + FXSYS_floor((double)m / 12);
1066 double mn = _Mod(m, 12);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001067
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001068 double t = _TimeFromYearMonth((int)ym, (int)mn);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001069
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001070 if (_YearFromTime(t) != ym || _MonthFromTime(t) != mn ||
1071 _DateFromTime(t) != 1)
1072 return GetNan();
1073 return _Day(t) + dt - 1;
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001074}
1075
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001076double JS_MakeTime(int nHour, int nMin, int nSec, int nMs) {
1077 if (!_isfinite(nHour) || !_isfinite(nMin) || !_isfinite(nSec) ||
1078 !_isfinite(nMs))
1079 return GetNan();
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001080
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001081 double h = _toInteger(nHour);
1082 double m = _toInteger(nMin);
1083 double s = _toInteger(nSec);
1084 double milli = _toInteger(nMs);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001085
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001086 return h * 3600000 + m * 60000 + s * 1000 + milli;
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001087}
1088
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001089double JS_MakeDate(double day, double time) {
1090 if (!_isfinite(day) || !_isfinite(time))
1091 return GetNan();
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001092
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001093 return day * 86400000 + time;
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001094}
1095
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001096bool JS_PortIsNan(double d) {
1097 return d != d;
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001098}
1099
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001100double JS_LocalTime(double d) {
1101 return JS_GetDateTime() + _getDaylightSavingTA(d);
John Abd-El-Malek5110c472014-05-17 22:33:34 -07001102}
1103
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001104// JavaScript time implement End.