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 |