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