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