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 "JS_Value.h"
8
9 #include <time.h>
10 #include <cmath>
11 #include <limits>
12
13 #include "Document.h"
14 #include "JS_Define.h"
15 #include "JS_Object.h"
16
17 static const FX_DWORD g_nan[2] = {0, 0x7FF80000};
GetNan()18 static double GetNan() {
19 return *(double*)g_nan;
20 }
21
22 /* ---------------------------- CJS_Value ---------------------------- */
23
CJS_Value(CJS_Runtime * pRuntime)24 CJS_Value::CJS_Value(CJS_Runtime* pRuntime)
25 : m_eType(VT_unknown), m_pJSRuntime(pRuntime) {
26 }
27
CJS_Value(CJS_Runtime * pRuntime,v8::Local<v8::Value> pValue,Type t)28 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, v8::Local<v8::Value> pValue, Type t)
29 : m_eType(t), m_pValue(pValue), m_pJSRuntime(pRuntime) {
30 }
31
CJS_Value(CJS_Runtime * pRuntime,const int & iValue)32 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const int& iValue)
33 : m_pJSRuntime(pRuntime) {
34 operator=(iValue);
35 }
36
CJS_Value(CJS_Runtime * pRuntime,const bool & bValue)37 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const bool& bValue)
38 : m_pJSRuntime(pRuntime) {
39 operator=(bValue);
40 }
41
CJS_Value(CJS_Runtime * pRuntime,const float & fValue)42 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const float& fValue)
43 : m_pJSRuntime(pRuntime) {
44 operator=(fValue);
45 }
46
CJS_Value(CJS_Runtime * pRuntime,const double & dValue)47 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const double& dValue)
48 : m_pJSRuntime(pRuntime) {
49 operator=(dValue);
50 }
51
CJS_Value(CJS_Runtime * pRuntime,v8::Local<v8::Object> pJsObj)52 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, v8::Local<v8::Object> pJsObj)
53 : m_pJSRuntime(pRuntime) {
54 operator=(pJsObj);
55 }
56
CJS_Value(CJS_Runtime * pRuntime,CJS_Object * pJsObj)57 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Object* pJsObj)
58 : m_pJSRuntime(pRuntime) {
59 operator=(pJsObj);
60 }
61
CJS_Value(CJS_Runtime * pRuntime,CJS_Document * pJsDoc)62 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Document* pJsDoc)
63 : m_pJSRuntime(pRuntime) {
64 m_eType = VT_object;
65 if (pJsDoc)
66 m_pValue = pJsDoc->ToV8Object();
67 }
68
CJS_Value(CJS_Runtime * pRuntime,const FX_WCHAR * pWstr)69 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_WCHAR* pWstr)
70 : m_pJSRuntime(pRuntime) {
71 operator=(pWstr);
72 }
73
CJS_Value(CJS_Runtime * pRuntime,const FX_CHAR * pStr)74 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_CHAR* pStr)
75 : m_pJSRuntime(pRuntime) {
76 operator=(pStr);
77 }
78
CJS_Value(CJS_Runtime * pRuntime,CJS_Array & array)79 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Array& array)
80 : m_pJSRuntime(pRuntime) {
81 operator=(array);
82 }
83
~CJS_Value()84 CJS_Value::~CJS_Value() {}
85
Attach(v8::Local<v8::Value> pValue,Type t)86 void CJS_Value::Attach(v8::Local<v8::Value> pValue, Type t) {
87 m_pValue = pValue;
88 m_eType = t;
89 }
90
Attach(CJS_Value * pValue)91 void CJS_Value::Attach(CJS_Value* pValue) {
92 if (pValue)
93 Attach(pValue->ToV8Value(), pValue->GetType());
94 }
95
Detach()96 void CJS_Value::Detach() {
97 m_pValue = v8::Local<v8::Value>();
98 m_eType = VT_unknown;
99 }
100
101 /* ----------------------------------------------------------------------------------------
102 */
103
ToInt() const104 int CJS_Value::ToInt() const {
105 return FXJS_ToInt32(m_pJSRuntime->GetIsolate(), m_pValue);
106 }
107
ToBool() const108 bool CJS_Value::ToBool() const {
109 return FXJS_ToBoolean(m_pJSRuntime->GetIsolate(), m_pValue);
110 }
111
ToDouble() const112 double CJS_Value::ToDouble() const {
113 return FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pValue);
114 }
115
ToFloat() const116 float CJS_Value::ToFloat() const {
117 return (float)ToDouble();
118 }
119
ToCJSObject() const120 CJS_Object* CJS_Value::ToCJSObject() const {
121 v8::Local<v8::Object> pObj =
122 FXJS_ToObject(m_pJSRuntime->GetIsolate(), m_pValue);
123 return (CJS_Object*)FXJS_GetPrivate(m_pJSRuntime->GetIsolate(), pObj);
124 }
125
ToV8Object() const126 v8::Local<v8::Object> CJS_Value::ToV8Object() const {
127 return FXJS_ToObject(m_pJSRuntime->GetIsolate(), m_pValue);
128 }
129
ToCFXWideString() const130 CFX_WideString CJS_Value::ToCFXWideString() const {
131 return FXJS_ToString(m_pJSRuntime->GetIsolate(), m_pValue);
132 }
133
ToCFXByteString() const134 CFX_ByteString CJS_Value::ToCFXByteString() const {
135 return CFX_ByteString::FromUnicode(ToCFXWideString());
136 }
137
ToV8Value() const138 v8::Local<v8::Value> CJS_Value::ToV8Value() const {
139 return m_pValue;
140 }
141
ToV8Array() const142 v8::Local<v8::Array> CJS_Value::ToV8Array() const {
143 if (IsArrayObject())
144 return v8::Local<v8::Array>::Cast(
145 FXJS_ToObject(m_pJSRuntime->GetIsolate(), m_pValue));
146 return v8::Local<v8::Array>();
147 }
148
149 /* ----------------------------------------------------------------------------------------
150 */
151
operator =(int iValue)152 void CJS_Value::operator=(int iValue) {
153 m_pValue = FXJS_NewNumber(m_pJSRuntime->GetIsolate(), iValue);
154 m_eType = VT_number;
155 }
156
operator =(bool bValue)157 void CJS_Value::operator=(bool bValue) {
158 m_pValue = FXJS_NewBoolean(m_pJSRuntime->GetIsolate(), bValue);
159 m_eType = VT_boolean;
160 }
161
operator =(double dValue)162 void CJS_Value::operator=(double dValue) {
163 m_pValue = FXJS_NewNumber(m_pJSRuntime->GetIsolate(), dValue);
164 m_eType = VT_number;
165 }
166
operator =(float fValue)167 void CJS_Value::operator=(float fValue) {
168 m_pValue = FXJS_NewNumber(m_pJSRuntime->GetIsolate(), fValue);
169 m_eType = VT_number;
170 }
171
operator =(v8::Local<v8::Object> pObj)172 void CJS_Value::operator=(v8::Local<v8::Object> pObj) {
173 m_pValue = FXJS_NewObject(m_pJSRuntime->GetIsolate(), pObj);
174 m_eType = VT_fxobject;
175 }
176
operator =(CJS_Object * pObj)177 void CJS_Value::operator=(CJS_Object* pObj) {
178 if (pObj)
179 operator=(pObj->ToV8Object());
180 }
181
operator =(CJS_Document * pJsDoc)182 void CJS_Value::operator=(CJS_Document* pJsDoc) {
183 m_eType = VT_object;
184 if (pJsDoc) {
185 m_pValue = pJsDoc->ToV8Object();
186 }
187 }
188
operator =(const FX_WCHAR * pWstr)189 void CJS_Value::operator=(const FX_WCHAR* pWstr) {
190 m_pValue = FXJS_NewString(m_pJSRuntime->GetIsolate(), (wchar_t*)pWstr);
191 m_eType = VT_string;
192 }
193
SetNull()194 void CJS_Value::SetNull() {
195 m_pValue = FXJS_NewNull();
196 m_eType = VT_null;
197 }
198
operator =(const FX_CHAR * pStr)199 void CJS_Value::operator=(const FX_CHAR* pStr) {
200 operator=(CFX_WideString::FromLocal(pStr).c_str());
201 }
202
operator =(CJS_Array & array)203 void CJS_Value::operator=(CJS_Array& array) {
204 m_pValue =
205 FXJS_NewObject2(m_pJSRuntime->GetIsolate(), (v8::Local<v8::Array>)array);
206 m_eType = VT_object;
207 }
208
operator =(CJS_Date & date)209 void CJS_Value::operator=(CJS_Date& date) {
210 m_pValue = FXJS_NewDate(m_pJSRuntime->GetIsolate(), (double)date);
211 m_eType = VT_date;
212 }
213
operator =(CJS_Value value)214 void CJS_Value::operator=(CJS_Value value) {
215 m_pValue = value.ToV8Value();
216 m_eType = value.m_eType;
217 m_pJSRuntime = value.m_pJSRuntime;
218 }
219
220 /* ----------------------------------------------------------------------------------------
221 */
222
GetType() const223 CJS_Value::Type CJS_Value::GetType() const {
224 if (m_pValue.IsEmpty())
225 return VT_unknown;
226 if (m_pValue->IsString())
227 return VT_string;
228 if (m_pValue->IsNumber())
229 return VT_number;
230 if (m_pValue->IsBoolean())
231 return VT_boolean;
232 if (m_pValue->IsDate())
233 return VT_date;
234 if (m_pValue->IsObject())
235 return VT_object;
236 if (m_pValue->IsNull())
237 return VT_null;
238 if (m_pValue->IsUndefined())
239 return VT_undefined;
240 return VT_unknown;
241 }
242
IsArrayObject() const243 FX_BOOL CJS_Value::IsArrayObject() const {
244 if (m_pValue.IsEmpty())
245 return FALSE;
246 return m_pValue->IsArray();
247 }
248
IsDateObject() const249 FX_BOOL CJS_Value::IsDateObject() const {
250 if (m_pValue.IsEmpty())
251 return FALSE;
252 return m_pValue->IsDate();
253 }
254
255 // CJS_Value::operator CJS_Array()
ConvertToArray(CJS_Array & array) const256 FX_BOOL CJS_Value::ConvertToArray(CJS_Array& array) const {
257 if (IsArrayObject()) {
258 array.Attach(FXJS_ToArray(m_pJSRuntime->GetIsolate(), m_pValue));
259 return TRUE;
260 }
261
262 return FALSE;
263 }
264
ConvertToDate(CJS_Date & date) const265 FX_BOOL CJS_Value::ConvertToDate(CJS_Date& date) const {
266 // if (GetType() == VT_date)
267 // {
268 // date = (double)(*this);
269 // return TRUE;
270 // }
271
272 if (IsDateObject()) {
273 date.Attach(m_pValue);
274 return TRUE;
275 }
276
277 return FALSE;
278 }
279
280 /* ---------------------------- CJS_PropValue ---------------------------- */
281
CJS_PropValue(const CJS_Value & value)282 CJS_PropValue::CJS_PropValue(const CJS_Value& value)
283 : CJS_Value(value), m_bIsSetting(0) {}
284
CJS_PropValue(CJS_Runtime * pRuntime)285 CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime)
286 : CJS_Value(pRuntime), m_bIsSetting(0) {
287 }
288
~CJS_PropValue()289 CJS_PropValue::~CJS_PropValue() {
290 }
291
operator <<(int iValue)292 void CJS_PropValue::operator<<(int iValue) {
293 ASSERT(!m_bIsSetting);
294 CJS_Value::operator=(iValue);
295 }
296
operator >>(int & iValue) const297 void CJS_PropValue::operator>>(int& iValue) const {
298 ASSERT(m_bIsSetting);
299 iValue = CJS_Value::ToInt();
300 }
301
operator <<(bool bValue)302 void CJS_PropValue::operator<<(bool bValue) {
303 ASSERT(!m_bIsSetting);
304 CJS_Value::operator=(bValue);
305 }
306
operator >>(bool & bValue) const307 void CJS_PropValue::operator>>(bool& bValue) const {
308 ASSERT(m_bIsSetting);
309 bValue = CJS_Value::ToBool();
310 }
311
operator <<(double dValue)312 void CJS_PropValue::operator<<(double dValue) {
313 ASSERT(!m_bIsSetting);
314 CJS_Value::operator=(dValue);
315 }
316
operator >>(double & dValue) const317 void CJS_PropValue::operator>>(double& dValue) const {
318 ASSERT(m_bIsSetting);
319 dValue = CJS_Value::ToDouble();
320 }
321
operator <<(CJS_Object * pObj)322 void CJS_PropValue::operator<<(CJS_Object* pObj) {
323 ASSERT(!m_bIsSetting);
324 CJS_Value::operator=(pObj);
325 }
326
operator >>(CJS_Object * & ppObj) const327 void CJS_PropValue::operator>>(CJS_Object*& ppObj) const {
328 ASSERT(m_bIsSetting);
329 ppObj = CJS_Value::ToCJSObject();
330 }
331
operator <<(CJS_Document * pJsDoc)332 void CJS_PropValue::operator<<(CJS_Document* pJsDoc) {
333 ASSERT(!m_bIsSetting);
334 CJS_Value::operator=(pJsDoc);
335 }
336
operator >>(CJS_Document * & ppJsDoc) const337 void CJS_PropValue::operator>>(CJS_Document*& ppJsDoc) const {
338 ASSERT(m_bIsSetting);
339 ppJsDoc = static_cast<CJS_Document*>(CJS_Value::ToCJSObject());
340 }
341
operator <<(v8::Local<v8::Object> pObj)342 void CJS_PropValue::operator<<(v8::Local<v8::Object> pObj) {
343 ASSERT(!m_bIsSetting);
344 CJS_Value::operator=(pObj);
345 }
346
operator >>(v8::Local<v8::Object> & ppObj) const347 void CJS_PropValue::operator>>(v8::Local<v8::Object>& ppObj) const {
348 ASSERT(m_bIsSetting);
349 ppObj = CJS_Value::ToV8Object();
350 }
351
StartSetting()352 void CJS_PropValue::StartSetting() {
353 m_bIsSetting = 1;
354 }
355
StartGetting()356 void CJS_PropValue::StartGetting() {
357 m_bIsSetting = 0;
358 }
operator <<(CFX_ByteString string)359 void CJS_PropValue::operator<<(CFX_ByteString string) {
360 ASSERT(!m_bIsSetting);
361 CJS_Value::operator=(string.c_str());
362 }
363
operator >>(CFX_ByteString & string) const364 void CJS_PropValue::operator>>(CFX_ByteString& string) const {
365 ASSERT(m_bIsSetting);
366 string = CJS_Value::ToCFXByteString();
367 }
368
operator <<(const FX_WCHAR * c_string)369 void CJS_PropValue::operator<<(const FX_WCHAR* c_string) {
370 ASSERT(!m_bIsSetting);
371 CJS_Value::operator=(c_string);
372 }
373
operator >>(CFX_WideString & wide_string) const374 void CJS_PropValue::operator>>(CFX_WideString& wide_string) const {
375 ASSERT(m_bIsSetting);
376 wide_string = CJS_Value::ToCFXWideString();
377 }
378
operator <<(CFX_WideString wide_string)379 void CJS_PropValue::operator<<(CFX_WideString wide_string) {
380 ASSERT(!m_bIsSetting);
381 CJS_Value::operator=(wide_string.c_str());
382 }
383
operator >>(CJS_Array & array) const384 void CJS_PropValue::operator>>(CJS_Array& array) const {
385 ASSERT(m_bIsSetting);
386 ConvertToArray(array);
387 }
388
operator <<(CJS_Array & array)389 void CJS_PropValue::operator<<(CJS_Array& array) {
390 ASSERT(!m_bIsSetting);
391 CJS_Value::operator=(array);
392 }
393
operator >>(CJS_Date & date) const394 void CJS_PropValue::operator>>(CJS_Date& date) const {
395 ASSERT(m_bIsSetting);
396 ConvertToDate(date);
397 }
398
operator <<(CJS_Date & date)399 void CJS_PropValue::operator<<(CJS_Date& date) {
400 ASSERT(!m_bIsSetting);
401 CJS_Value::operator=(date);
402 }
403
operator v8::Local<v8::Value>() const404 CJS_PropValue::operator v8::Local<v8::Value>() const {
405 return m_pValue;
406 }
407
CJS_Array(CJS_Runtime * pRuntime)408 CJS_Array::CJS_Array(CJS_Runtime* pRuntime) : m_pJSRuntime(pRuntime) {
409 }
410
~CJS_Array()411 CJS_Array::~CJS_Array() {}
412
Attach(v8::Local<v8::Array> pArray)413 void CJS_Array::Attach(v8::Local<v8::Array> pArray) {
414 m_pArray = pArray;
415 }
416
IsAttached()417 FX_BOOL CJS_Array::IsAttached() {
418 return FALSE;
419 }
420
GetElement(unsigned index,CJS_Value & value)421 void CJS_Array::GetElement(unsigned index, CJS_Value& value) {
422 if (m_pArray.IsEmpty())
423 return;
424 v8::Local<v8::Value> p =
425 FXJS_GetArrayElement(m_pJSRuntime->GetIsolate(), m_pArray, index);
426 value.Attach(p, CJS_Value::VT_object);
427 }
428
SetElement(unsigned index,CJS_Value value)429 void CJS_Array::SetElement(unsigned index, CJS_Value value) {
430 if (m_pArray.IsEmpty())
431 m_pArray = FXJS_NewArray(m_pJSRuntime->GetIsolate());
432
433 FXJS_PutArrayElement(m_pJSRuntime->GetIsolate(), m_pArray, index,
434 value.ToV8Value());
435 }
436
GetLength()437 int CJS_Array::GetLength() {
438 if (m_pArray.IsEmpty())
439 return 0;
440 return FXJS_GetArrayLength(m_pArray);
441 }
442
operator v8::Local<v8::Array>()443 CJS_Array::operator v8::Local<v8::Array>() {
444 if (m_pArray.IsEmpty())
445 m_pArray = FXJS_NewArray(m_pJSRuntime->GetIsolate());
446
447 return m_pArray;
448 }
449
CJS_Date(CJS_Runtime * pRuntime)450 CJS_Date::CJS_Date(CJS_Runtime* pRuntime) : m_pJSRuntime(pRuntime) {
451 }
452
CJS_Date(CJS_Runtime * pRuntime,double dMsecTime)453 CJS_Date::CJS_Date(CJS_Runtime* pRuntime, double dMsecTime)
454 : m_pJSRuntime(pRuntime) {
455 m_pDate = FXJS_NewDate(pRuntime->GetIsolate(), dMsecTime);
456 }
457
CJS_Date(CJS_Runtime * pRuntime,int year,int mon,int day,int hour,int min,int sec)458 CJS_Date::CJS_Date(CJS_Runtime* pRuntime,
459 int year,
460 int mon,
461 int day,
462 int hour,
463 int min,
464 int sec)
465 : m_pJSRuntime(pRuntime) {
466 m_pDate = FXJS_NewDate(pRuntime->GetIsolate(),
467 MakeDate(year, mon, day, hour, min, sec, 0));
468 }
469
MakeDate(int year,int mon,int day,int hour,int min,int sec,int ms)470 double CJS_Date::MakeDate(int year,
471 int mon,
472 int day,
473 int hour,
474 int min,
475 int sec,
476 int ms) {
477 return JS_MakeDate(JS_MakeDay(year, mon, day),
478 JS_MakeTime(hour, min, sec, ms));
479 }
480
~CJS_Date()481 CJS_Date::~CJS_Date() {}
482
IsValidDate()483 FX_BOOL CJS_Date::IsValidDate() {
484 if (m_pDate.IsEmpty())
485 return FALSE;
486 return !JS_PortIsNan(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate));
487 }
488
Attach(v8::Local<v8::Value> pDate)489 void CJS_Date::Attach(v8::Local<v8::Value> pDate) {
490 m_pDate = pDate;
491 }
492
GetYear()493 int CJS_Date::GetYear() {
494 if (IsValidDate())
495 return JS_GetYearFromTime(
496 JS_LocalTime(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate)));
497
498 return 0;
499 }
500
SetYear(int iYear)501 void CJS_Date::SetYear(int iYear) {
502 double date = MakeDate(iYear, GetMonth(), GetDay(), GetHours(), GetMinutes(),
503 GetSeconds(), 0);
504 FXJS_ValueCopy(m_pDate, FXJS_NewDate(m_pJSRuntime->GetIsolate(), date));
505 }
506
GetMonth()507 int CJS_Date::GetMonth() {
508 if (IsValidDate())
509 return JS_GetMonthFromTime(
510 JS_LocalTime(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate)));
511
512 return 0;
513 }
514
SetMonth(int iMonth)515 void CJS_Date::SetMonth(int iMonth) {
516 double date = MakeDate(GetYear(), iMonth, GetDay(), GetHours(), GetMinutes(),
517 GetSeconds(), 0);
518 FXJS_ValueCopy(m_pDate, FXJS_NewDate(m_pJSRuntime->GetIsolate(), date));
519 }
520
GetDay()521 int CJS_Date::GetDay() {
522 if (IsValidDate())
523 return JS_GetDayFromTime(
524 JS_LocalTime(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate)));
525
526 return 0;
527 }
528
SetDay(int iDay)529 void CJS_Date::SetDay(int iDay) {
530 double date = MakeDate(GetYear(), GetMonth(), iDay, GetHours(), GetMinutes(),
531 GetSeconds(), 0);
532 FXJS_ValueCopy(m_pDate, FXJS_NewDate(m_pJSRuntime->GetIsolate(), date));
533 }
534
GetHours()535 int CJS_Date::GetHours() {
536 if (IsValidDate())
537 return JS_GetHourFromTime(
538 JS_LocalTime(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate)));
539
540 return 0;
541 }
542
SetHours(int iHours)543 void CJS_Date::SetHours(int iHours) {
544 double date = MakeDate(GetYear(), GetMonth(), GetDay(), iHours, GetMinutes(),
545 GetSeconds(), 0);
546 FXJS_ValueCopy(m_pDate, FXJS_NewDate(m_pJSRuntime->GetIsolate(), date));
547 }
548
GetMinutes()549 int CJS_Date::GetMinutes() {
550 if (IsValidDate())
551 return JS_GetMinFromTime(
552 JS_LocalTime(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate)));
553
554 return 0;
555 }
556
SetMinutes(int minutes)557 void CJS_Date::SetMinutes(int minutes) {
558 double date = MakeDate(GetYear(), GetMonth(), GetDay(), GetHours(), minutes,
559 GetSeconds(), 0);
560 FXJS_ValueCopy(m_pDate, FXJS_NewDate(m_pJSRuntime->GetIsolate(), date));
561 }
562
GetSeconds()563 int CJS_Date::GetSeconds() {
564 if (IsValidDate())
565 return JS_GetSecFromTime(
566 JS_LocalTime(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate)));
567
568 return 0;
569 }
570
SetSeconds(int seconds)571 void CJS_Date::SetSeconds(int seconds) {
572 double date = MakeDate(GetYear(), GetMonth(), GetDay(), GetHours(),
573 GetMinutes(), seconds, 0);
574 FXJS_ValueCopy(m_pDate, FXJS_NewDate(m_pJSRuntime->GetIsolate(), date));
575 }
576
operator v8::Local<v8::Value>()577 CJS_Date::operator v8::Local<v8::Value>() {
578 return m_pDate;
579 }
580
operator double() const581 CJS_Date::operator double() const {
582 if (m_pDate.IsEmpty())
583 return 0.0;
584 return FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pDate);
585 }
586
ToString() const587 CFX_WideString CJS_Date::ToString() const {
588 if (m_pDate.IsEmpty())
589 return L"";
590 return FXJS_ToString(m_pJSRuntime->GetIsolate(), m_pDate);
591 }
592
_getLocalTZA()593 double _getLocalTZA() {
594 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
595 return 0;
596 time_t t = 0;
597 time(&t);
598 localtime(&t);
599 #if _MSC_VER >= 1900
600 // In gcc and in Visual Studio prior to VS 2015 'timezone' is a global
601 // variable declared in time.h. That variable was deprecated and in VS 2015
602 // is removed, with _get_timezone replacing it.
603 long timezone = 0;
604 _get_timezone(&timezone);
605 #endif
606 return (double)(-(timezone * 1000));
607 }
608
_getDaylightSavingTA(double d)609 int _getDaylightSavingTA(double d) {
610 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
611 return 0;
612 time_t t = (time_t)(d / 1000);
613 struct tm* tmp = localtime(&t);
614 if (!tmp)
615 return 0;
616 if (tmp->tm_isdst > 0)
617 // One hour.
618 return (int)60 * 60 * 1000;
619 return 0;
620 }
621
_Mod(double x,double y)622 double _Mod(double x, double y) {
623 double r = fmod(x, y);
624 if (r < 0)
625 r += y;
626 return r;
627 }
628
_isfinite(double v)629 int _isfinite(double v) {
630 #if _MSC_VER
631 return ::_finite(v);
632 #else
633 return std::fabs(v) < std::numeric_limits<double>::max();
634 #endif
635 }
636
_toInteger(double n)637 double _toInteger(double n) {
638 return (n >= 0) ? FXSYS_floor(n) : -FXSYS_floor(-n);
639 }
640
_isLeapYear(int year)641 bool _isLeapYear(int year) {
642 return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0));
643 }
644
_DayFromYear(int y)645 int _DayFromYear(int y) {
646 return (int)(365 * (y - 1970.0) + FXSYS_floor((y - 1969.0) / 4) -
647 FXSYS_floor((y - 1901.0) / 100) +
648 FXSYS_floor((y - 1601.0) / 400));
649 }
650
_TimeFromYear(int y)651 double _TimeFromYear(int y) {
652 return 86400000.0 * _DayFromYear(y);
653 }
654
_TimeFromYearMonth(int y,int m)655 double _TimeFromYearMonth(int y, int m) {
656 static int daysMonth[12] = {
657 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
658 static int leapDaysMonth[12] = {
659 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};
660 int* pMonth = daysMonth;
661 if (_isLeapYear(y))
662 pMonth = leapDaysMonth;
663 return _TimeFromYear(y) + ((double)pMonth[m]) * 86400000;
664 }
665
_Day(double t)666 int _Day(double t) {
667 return (int)FXSYS_floor(t / 86400000);
668 }
669
_YearFromTime(double t)670 int _YearFromTime(double t) {
671 // estimate the time.
672 int y = 1970 + static_cast<int>(t / (365.2425 * 86400000));
673 if (_TimeFromYear(y) <= t) {
674 while (_TimeFromYear(y + 1) <= t)
675 y++;
676 } else
677 while (_TimeFromYear(y) > t)
678 y--;
679 return y;
680 }
681
_DayWithinYear(double t)682 int _DayWithinYear(double t) {
683 int year = _YearFromTime(t);
684 int day = _Day(t);
685 return day - _DayFromYear(year);
686 }
687
_MonthFromTime(double t)688 int _MonthFromTime(double t) {
689 int day = _DayWithinYear(t);
690 int year = _YearFromTime(t);
691 if (0 <= day && day < 31)
692 return 0;
693 if (31 <= day && day < 59 + _isLeapYear(year))
694 return 1;
695 if ((59 + _isLeapYear(year)) <= day && day < (90 + _isLeapYear(year)))
696 return 2;
697 if ((90 + _isLeapYear(year)) <= day && day < (120 + _isLeapYear(year)))
698 return 3;
699 if ((120 + _isLeapYear(year)) <= day && day < (151 + _isLeapYear(year)))
700 return 4;
701 if ((151 + _isLeapYear(year)) <= day && day < (181 + _isLeapYear(year)))
702 return 5;
703 if ((181 + _isLeapYear(year)) <= day && day < (212 + _isLeapYear(year)))
704 return 6;
705 if ((212 + _isLeapYear(year)) <= day && day < (243 + _isLeapYear(year)))
706 return 7;
707 if ((243 + _isLeapYear(year)) <= day && day < (273 + _isLeapYear(year)))
708 return 8;
709 if ((273 + _isLeapYear(year)) <= day && day < (304 + _isLeapYear(year)))
710 return 9;
711 if ((304 + _isLeapYear(year)) <= day && day < (334 + _isLeapYear(year)))
712 return 10;
713 if ((334 + _isLeapYear(year)) <= day && day < (365 + _isLeapYear(year)))
714 return 11;
715
716 return -1;
717 }
718
_DateFromTime(double t)719 int _DateFromTime(double t) {
720 int day = _DayWithinYear(t);
721 int year = _YearFromTime(t);
722 bool leap = _isLeapYear(year);
723 int month = _MonthFromTime(t);
724 switch (month) {
725 case 0:
726 return day + 1;
727 case 1:
728 return day - 30;
729 case 2:
730 return day - 58 - leap;
731 case 3:
732 return day - 89 - leap;
733 case 4:
734 return day - 119 - leap;
735 case 5:
736 return day - 150 - leap;
737 case 6:
738 return day - 180 - leap;
739 case 7:
740 return day - 211 - leap;
741 case 8:
742 return day - 242 - leap;
743 case 9:
744 return day - 272 - leap;
745 case 10:
746 return day - 303 - leap;
747 case 11:
748 return day - 333 - leap;
749 default:
750 return 0;
751 }
752 }
753
JS_GetDateTime()754 double JS_GetDateTime() {
755 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
756 return 0;
757 time_t t = time(NULL);
758 struct tm* pTm = localtime(&t);
759
760 int year = pTm->tm_year + 1900;
761 double t1 = _TimeFromYear(year);
762
763 return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 +
764 pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0;
765 }
766
JS_GetYearFromTime(double dt)767 int JS_GetYearFromTime(double dt) {
768 return _YearFromTime(dt);
769 }
770
JS_GetMonthFromTime(double dt)771 int JS_GetMonthFromTime(double dt) {
772 return _MonthFromTime(dt);
773 }
774
JS_GetDayFromTime(double dt)775 int JS_GetDayFromTime(double dt) {
776 return _DateFromTime(dt);
777 }
778
JS_GetHourFromTime(double dt)779 int JS_GetHourFromTime(double dt) {
780 return (int)_Mod(FXSYS_floor((double)(dt / (60 * 60 * 1000))), 24);
781 }
782
JS_GetMinFromTime(double dt)783 int JS_GetMinFromTime(double dt) {
784 return (int)_Mod(FXSYS_floor((double)(dt / (60 * 1000))), 60);
785 }
786
JS_GetSecFromTime(double dt)787 int JS_GetSecFromTime(double dt) {
788 return (int)_Mod(FXSYS_floor((double)(dt / 1000)), 60);
789 }
790
JS_DateParse(const wchar_t * string)791 double JS_DateParse(const wchar_t* string) {
792 v8::Isolate* pIsolate = v8::Isolate::GetCurrent();
793 v8::Isolate::Scope isolate_scope(pIsolate);
794 v8::HandleScope scope(pIsolate);
795
796 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
797
798 // Use the built-in object method.
799 v8::Local<v8::Value> v =
800 context->Global()
801 ->Get(context, v8::String::NewFromUtf8(pIsolate, "Date",
802 v8::NewStringType::kNormal)
803 .ToLocalChecked())
804 .ToLocalChecked();
805 if (v->IsObject()) {
806 v8::Local<v8::Object> o = v->ToObject(context).ToLocalChecked();
807 v = o->Get(context, v8::String::NewFromUtf8(pIsolate, "parse",
808 v8::NewStringType::kNormal)
809 .ToLocalChecked()).ToLocalChecked();
810 if (v->IsFunction()) {
811 v8::Local<v8::Function> funC = v8::Local<v8::Function>::Cast(v);
812
813 const int argc = 1;
814 v8::Local<v8::String> timeStr = FXJS_WSToJSString(pIsolate, string);
815 v8::Local<v8::Value> argv[argc] = {timeStr};
816 v = funC->Call(context, context->Global(), argc, argv).ToLocalChecked();
817 if (v->IsNumber()) {
818 double date = v->ToNumber(context).ToLocalChecked()->Value();
819 if (!_isfinite(date))
820 return date;
821 return date + _getLocalTZA() + _getDaylightSavingTA(date);
822 }
823 }
824 }
825 return 0;
826 }
827
JS_MakeDay(int nYear,int nMonth,int nDate)828 double JS_MakeDay(int nYear, int nMonth, int nDate) {
829 if (!_isfinite(nYear) || !_isfinite(nMonth) || !_isfinite(nDate))
830 return GetNan();
831 double y = _toInteger(nYear);
832 double m = _toInteger(nMonth);
833 double dt = _toInteger(nDate);
834 double ym = y + FXSYS_floor((double)m / 12);
835 double mn = _Mod(m, 12);
836
837 double t = _TimeFromYearMonth((int)ym, (int)mn);
838
839 if (_YearFromTime(t) != ym || _MonthFromTime(t) != mn ||
840 _DateFromTime(t) != 1)
841 return GetNan();
842 return _Day(t) + dt - 1;
843 }
844
JS_MakeTime(int nHour,int nMin,int nSec,int nMs)845 double JS_MakeTime(int nHour, int nMin, int nSec, int nMs) {
846 if (!_isfinite(nHour) || !_isfinite(nMin) || !_isfinite(nSec) ||
847 !_isfinite(nMs))
848 return GetNan();
849
850 double h = _toInteger(nHour);
851 double m = _toInteger(nMin);
852 double s = _toInteger(nSec);
853 double milli = _toInteger(nMs);
854
855 return h * 3600000 + m * 60000 + s * 1000 + milli;
856 }
857
JS_MakeDate(double day,double time)858 double JS_MakeDate(double day, double time) {
859 if (!_isfinite(day) || !_isfinite(time))
860 return GetNan();
861
862 return day * 86400000 + time;
863 }
864
JS_PortIsNan(double d)865 bool JS_PortIsNan(double d) {
866 return d != d;
867 }
868
JS_LocalTime(double d)869 double JS_LocalTime(double d) {
870 return JS_GetDateTime() + _getDaylightSavingTA(d);
871 }
872