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