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