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