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