Home | History | Annotate | Download | only in javascript
      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(CJS_Runtime* pRuntime)
     25     : m_eType(VT_unknown), m_pJSRuntime(pRuntime) {
     26 }
     27 
     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 
     32 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const int& iValue)
     33     : m_pJSRuntime(pRuntime) {
     34   operator=(iValue);
     35 }
     36 
     37 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const bool& bValue)
     38     : m_pJSRuntime(pRuntime) {
     39   operator=(bValue);
     40 }
     41 
     42 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const float& fValue)
     43     : m_pJSRuntime(pRuntime) {
     44   operator=(fValue);
     45 }
     46 
     47 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const double& dValue)
     48     : m_pJSRuntime(pRuntime) {
     49   operator=(dValue);
     50 }
     51 
     52 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, v8::Local<v8::Object> pJsObj)
     53     : m_pJSRuntime(pRuntime) {
     54   operator=(pJsObj);
     55 }
     56 
     57 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Object* pJsObj)
     58     : m_pJSRuntime(pRuntime) {
     59   operator=(pJsObj);
     60 }
     61 
     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 
     69 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_WCHAR* pWstr)
     70     : m_pJSRuntime(pRuntime) {
     71   operator=(pWstr);
     72 }
     73 
     74 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_CHAR* pStr)
     75     : m_pJSRuntime(pRuntime) {
     76   operator=(pStr);
     77 }
     78 
     79 CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Array& array)
     80     : m_pJSRuntime(pRuntime) {
     81   operator=(array);
     82 }
     83 
     84 CJS_Value::~CJS_Value() {}
     85 
     86 void CJS_Value::Attach(v8::Local<v8::Value> pValue, Type t) {
     87   m_pValue = pValue;
     88   m_eType = t;
     89 }
     90 
     91 void CJS_Value::Attach(CJS_Value* pValue) {
     92   if (pValue)
     93     Attach(pValue->ToV8Value(), pValue->GetType());
     94 }
     95 
     96 void CJS_Value::Detach() {
     97   m_pValue = v8::Local<v8::Value>();
     98   m_eType = VT_unknown;
     99 }
    100 
    101 /* ----------------------------------------------------------------------------------------
    102  */
    103 
    104 int CJS_Value::ToInt() const {
    105   return FXJS_ToInt32(m_pJSRuntime->GetIsolate(), m_pValue);
    106 }
    107 
    108 bool CJS_Value::ToBool() const {
    109   return FXJS_ToBoolean(m_pJSRuntime->GetIsolate(), m_pValue);
    110 }
    111 
    112 double CJS_Value::ToDouble() const {
    113   return FXJS_ToNumber(m_pJSRuntime->GetIsolate(), m_pValue);
    114 }
    115 
    116 float CJS_Value::ToFloat() const {
    117   return (float)ToDouble();
    118 }
    119 
    120 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 
    126 v8::Local<v8::Object> CJS_Value::ToV8Object() const {
    127   return FXJS_ToObject(m_pJSRuntime->GetIsolate(), m_pValue);
    128 }
    129 
    130 CFX_WideString CJS_Value::ToCFXWideString() const {
    131   return FXJS_ToString(m_pJSRuntime->GetIsolate(), m_pValue);
    132 }
    133 
    134 CFX_ByteString CJS_Value::ToCFXByteString() const {
    135   return CFX_ByteString::FromUnicode(ToCFXWideString());
    136 }
    137 
    138 v8::Local<v8::Value> CJS_Value::ToV8Value() const {
    139   return m_pValue;
    140 }
    141 
    142 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 
    152 void CJS_Value::operator=(int iValue) {
    153   m_pValue = FXJS_NewNumber(m_pJSRuntime->GetIsolate(), iValue);
    154   m_eType = VT_number;
    155 }
    156 
    157 void CJS_Value::operator=(bool bValue) {
    158   m_pValue = FXJS_NewBoolean(m_pJSRuntime->GetIsolate(), bValue);
    159   m_eType = VT_boolean;
    160 }
    161 
    162 void CJS_Value::operator=(double dValue) {
    163   m_pValue = FXJS_NewNumber(m_pJSRuntime->GetIsolate(), dValue);
    164   m_eType = VT_number;
    165 }
    166 
    167 void CJS_Value::operator=(float fValue) {
    168   m_pValue = FXJS_NewNumber(m_pJSRuntime->GetIsolate(), fValue);
    169   m_eType = VT_number;
    170 }
    171 
    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 
    177 void CJS_Value::operator=(CJS_Object* pObj) {
    178   if (pObj)
    179     operator=(pObj->ToV8Object());
    180 }
    181 
    182 void CJS_Value::operator=(CJS_Document* pJsDoc) {
    183   m_eType = VT_object;
    184   if (pJsDoc) {
    185     m_pValue = pJsDoc->ToV8Object();
    186   }
    187 }
    188 
    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 
    194 void CJS_Value::SetNull() {
    195   m_pValue = FXJS_NewNull();
    196   m_eType = VT_null;
    197 }
    198 
    199 void CJS_Value::operator=(const FX_CHAR* pStr) {
    200   operator=(CFX_WideString::FromLocal(pStr).c_str());
    201 }
    202 
    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 
    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 
    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 
    223 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 
    243 FX_BOOL CJS_Value::IsArrayObject() const {
    244   if (m_pValue.IsEmpty())
    245     return FALSE;
    246   return m_pValue->IsArray();
    247 }
    248 
    249 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()
    256 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 
    265 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 
    282 CJS_PropValue::CJS_PropValue(const CJS_Value& value)
    283     : CJS_Value(value), m_bIsSetting(0) {}
    284 
    285 CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime)
    286     : CJS_Value(pRuntime), m_bIsSetting(0) {
    287 }
    288 
    289 CJS_PropValue::~CJS_PropValue() {
    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::CJS_Array(CJS_Runtime* pRuntime) : m_pJSRuntime(pRuntime) {
    409 }
    410 
    411 CJS_Array::~CJS_Array() {}
    412 
    413 void CJS_Array::Attach(v8::Local<v8::Array> pArray) {
    414   m_pArray = pArray;
    415 }
    416 
    417 FX_BOOL CJS_Array::IsAttached() {
    418   return FALSE;
    419 }
    420 
    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 
    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 
    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_pJSRuntime->GetIsolate());
    446 
    447   return m_pArray;
    448 }
    449 
    450 CJS_Date::CJS_Date(CJS_Runtime* pRuntime) : m_pJSRuntime(pRuntime) {
    451 }
    452 
    453 CJS_Date::CJS_Date(CJS_Runtime* pRuntime, double dMsecTime)
    454     : m_pJSRuntime(pRuntime) {
    455   m_pDate = FXJS_NewDate(pRuntime->GetIsolate(), dMsecTime);
    456 }
    457 
    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 
    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_pJSRuntime->GetIsolate(), 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(
    496         JS_LocalTime(FXJS_ToNumber(m_pJSRuntime->GetIsolate(), 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_pJSRuntime->GetIsolate(), date));
    505 }
    506 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    577 CJS_Date::operator v8::Local<v8::Value>() {
    578   return m_pDate;
    579 }
    580 
    581 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 
    587 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 
    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 
    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 
    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 
    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 
    637 double _toInteger(double n) {
    638   return (n >= 0) ? FXSYS_floor(n) : -FXSYS_floor(-n);
    639 }
    640 
    641 bool _isLeapYear(int year) {
    642   return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0));
    643 }
    644 
    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 
    651 double _TimeFromYear(int y) {
    652   return 86400000.0 * _DayFromYear(y);
    653 }
    654 
    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 
    666 int _Day(double t) {
    667   return (int)FXSYS_floor(t / 86400000);
    668 }
    669 
    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 
    682 int _DayWithinYear(double t) {
    683   int year = _YearFromTime(t);
    684   int day = _Day(t);
    685   return day - _DayFromYear(year);
    686 }
    687 
    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 
    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 
    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 
    767 int JS_GetYearFromTime(double dt) {
    768   return _YearFromTime(dt);
    769 }
    770 
    771 int JS_GetMonthFromTime(double dt) {
    772   return _MonthFromTime(dt);
    773 }
    774 
    775 int JS_GetDayFromTime(double dt) {
    776   return _DateFromTime(dt);
    777 }
    778 
    779 int JS_GetHourFromTime(double dt) {
    780   return (int)_Mod(FXSYS_floor((double)(dt / (60 * 60 * 1000))), 24);
    781 }
    782 
    783 int JS_GetMinFromTime(double dt) {
    784   return (int)_Mod(FXSYS_floor((double)(dt / (60 * 1000))), 60);
    785 }
    786 
    787 int JS_GetSecFromTime(double dt) {
    788   return (int)_Mod(FXSYS_floor((double)(dt / 1000)), 60);
    789 }
    790 
    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 
    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 
    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 
    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 
    865 bool JS_PortIsNan(double d) {
    866   return d != d;
    867 }
    868 
    869 double JS_LocalTime(double d) {
    870   return JS_GetDateTime() + _getDaylightSavingTA(d);
    871 }
    872