Remove some abstractions in fxjs_v8.h.
[pdfium.git] / fpdfsdk / src / javascript / JS_Value.cpp
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 "../../include/javascript/JavaScript.h"
8 #include "../../include/javascript/JS_Define.h"
9 #include "../../include/javascript/JS_Object.h"
10 #include "../../include/javascript/JS_Value.h"
11 #include "../../include/javascript/Document.h"
12
13 /* ---------------------------- CJS_Value ---------------------------- */
14
15 CJS_Value::CJS_Value(v8::Isolate* isolate)
16     : m_eType(VT_unknown), m_isolate(isolate) {}
17 CJS_Value::CJS_Value(v8::Isolate* isolate,
18                      v8::Local<v8::Value> pValue,
19                      FXJSVALUETYPE t)
20     : m_pValue(pValue), m_eType(t), m_isolate(isolate) {}
21
22 CJS_Value::CJS_Value(v8::Isolate* isolate, const int& iValue)
23     : m_isolate(isolate) {
24   operator=(iValue);
25 }
26
27 CJS_Value::CJS_Value(v8::Isolate* isolate, const bool& bValue)
28     : m_isolate(isolate) {
29   operator=(bValue);
30 }
31
32 CJS_Value::CJS_Value(v8::Isolate* isolate, const float& fValue)
33     : m_isolate(isolate) {
34   operator=(fValue);
35 }
36
37 CJS_Value::CJS_Value(v8::Isolate* isolate, const double& dValue)
38     : m_isolate(isolate) {
39   operator=(dValue);
40 }
41
42 CJS_Value::CJS_Value(v8::Isolate* isolate, v8::Local<v8::Object> pJsObj)
43     : m_isolate(isolate) {
44   operator=(pJsObj);
45 }
46
47 CJS_Value::CJS_Value(v8::Isolate* isolate, CJS_Object* pJsObj)
48     : m_isolate(isolate) {
49   operator=(pJsObj);
50 }
51
52 CJS_Value::CJS_Value(v8::Isolate* isolate, CJS_Document* pJsDoc)
53     : m_isolate(isolate) {
54   m_eType = VT_object;
55   if (pJsDoc)
56     m_pValue = (v8::Local<v8::Object>)*pJsDoc;
57 }
58
59 CJS_Value::CJS_Value(v8::Isolate* isolate, const FX_WCHAR* pWstr)
60     : m_isolate(isolate) {
61   operator=(pWstr);
62 }
63
64 CJS_Value::CJS_Value(v8::Isolate* isolate, const FX_CHAR* pStr)
65     : m_isolate(isolate) {
66   operator=(pStr);
67 }
68
69 CJS_Value::CJS_Value(v8::Isolate* isolate, CJS_Array& array)
70     : m_isolate(isolate) {
71   operator=(array);
72 }
73
74 CJS_Value::~CJS_Value() {}
75
76 void CJS_Value::Attach(v8::Local<v8::Value> pValue, FXJSVALUETYPE t) {
77   m_pValue = pValue;
78   m_eType = t;
79 }
80
81 void CJS_Value::Attach(CJS_Value* pValue) {
82   if (pValue)
83     Attach(pValue->ToV8Value(), pValue->GetType());
84 }
85
86 void CJS_Value::Detach() {
87   m_pValue = v8::Local<v8::Value>();
88   m_eType = VT_unknown;
89 }
90
91 /* ----------------------------------------------------------------------------------------
92  */
93
94 int CJS_Value::ToInt() const {
95   return JS_ToInt32(m_isolate, m_pValue);
96 }
97
98 bool CJS_Value::ToBool() const {
99   return JS_ToBoolean(m_isolate, m_pValue);
100 }
101
102 double CJS_Value::ToDouble() const {
103   return JS_ToNumber(m_isolate, m_pValue);
104 }
105
106 float CJS_Value::ToFloat() const {
107   return (float)ToDouble();
108 }
109
110 CJS_Object* CJS_Value::ToCJSObject() const {
111   v8::Local<v8::Object> pObj = JS_ToObject(m_isolate, m_pValue);
112   return (CJS_Object*)JS_GetPrivate(m_isolate, pObj);
113 }
114
115 v8::Local<v8::Object> CJS_Value::ToV8Object() const {
116   return JS_ToObject(m_isolate, m_pValue);
117 }
118
119 CFX_WideString CJS_Value::ToCFXWideString() const {
120   return JS_ToString(m_isolate, m_pValue);
121 }
122
123 CFX_ByteString CJS_Value::ToCFXByteString() const {
124   return CFX_ByteString::FromUnicode(ToCFXWideString());
125 }
126
127 v8::Local<v8::Value> CJS_Value::ToV8Value() const {
128   return m_pValue;
129 }
130
131 v8::Local<v8::Array> CJS_Value::ToV8Array() const {
132   if (IsArrayObject())
133     return v8::Local<v8::Array>::Cast(JS_ToObject(m_isolate, m_pValue));
134   return v8::Local<v8::Array>();
135 }
136
137 /* ----------------------------------------------------------------------------------------
138  */
139
140 void CJS_Value::operator=(int iValue) {
141   m_pValue = JS_NewNumber(m_isolate, iValue);
142
143   m_eType = VT_number;
144 }
145
146 void CJS_Value::operator=(bool bValue) {
147   m_pValue = JS_NewBoolean(m_isolate, bValue);
148
149   m_eType = VT_boolean;
150 }
151
152 void CJS_Value::operator=(double dValue) {
153   m_pValue = JS_NewNumber(m_isolate, dValue);
154
155   m_eType = VT_number;
156 }
157
158 void CJS_Value::operator=(float fValue) {
159   m_pValue = JS_NewNumber(m_isolate, fValue);
160   m_eType = VT_number;
161 }
162
163 void CJS_Value::operator=(v8::Local<v8::Object> pObj) {
164   m_pValue = JS_NewObject(m_isolate, pObj);
165
166   m_eType = VT_fxobject;
167 }
168
169 void CJS_Value::operator=(CJS_Object* pObj) {
170   if (pObj)
171     operator=((v8::Local<v8::Object>)*pObj);
172 }
173
174 void CJS_Value::operator=(CJS_Document* pJsDoc) {
175   m_eType = VT_object;
176   if (pJsDoc) {
177     m_pValue = static_cast<v8::Local<v8::Object>>(*pJsDoc);
178   }
179 }
180
181 void CJS_Value::operator=(const FX_WCHAR* pWstr) {
182   m_pValue = JS_NewString(m_isolate, (wchar_t*)pWstr);
183
184   m_eType = VT_string;
185 }
186
187 void CJS_Value::SetNull() {
188   m_pValue = JS_NewNull();
189
190   m_eType = VT_null;
191 }
192
193 void CJS_Value::operator=(const FX_CHAR* pStr) {
194   operator=(CFX_WideString::FromLocal(pStr).c_str());
195 }
196
197 void CJS_Value::operator=(CJS_Array& array) {
198   m_pValue = JS_NewObject2(m_isolate, (v8::Local<v8::Array>)array);
199
200   m_eType = VT_object;
201 }
202
203 void CJS_Value::operator=(CJS_Date& date) {
204   m_pValue = JS_NewDate(m_isolate, (double)date);
205
206   m_eType = VT_date;
207 }
208
209 void CJS_Value::operator=(CJS_Value value) {
210   m_pValue = value.ToV8Value();
211
212   m_eType = value.m_eType;
213   m_isolate = value.m_isolate;
214 }
215
216 /* ----------------------------------------------------------------------------------------
217  */
218
219 FXJSVALUETYPE CJS_Value::GetType() const {
220   if (m_pValue.IsEmpty())
221     return VT_unknown;
222   if (m_pValue->IsString())
223     return VT_string;
224   if (m_pValue->IsNumber())
225     return VT_number;
226   if (m_pValue->IsBoolean())
227     return VT_boolean;
228   if (m_pValue->IsDate())
229     return VT_date;
230   if (m_pValue->IsObject())
231     return VT_object;
232   if (m_pValue->IsNull())
233     return VT_null;
234   if (m_pValue->IsUndefined())
235     return VT_undefined;
236   return VT_unknown;
237 }
238
239 FX_BOOL CJS_Value::IsArrayObject() const {
240   if (m_pValue.IsEmpty())
241     return FALSE;
242   return m_pValue->IsArray();
243 }
244
245 FX_BOOL CJS_Value::IsDateObject() const {
246   if (m_pValue.IsEmpty())
247     return FALSE;
248   return m_pValue->IsDate();
249 }
250
251 // CJS_Value::operator CJS_Array()
252 FX_BOOL CJS_Value::ConvertToArray(CJS_Array& array) const {
253   if (IsArrayObject()) {
254     array.Attach(JS_ToArray(m_isolate, m_pValue));
255     return TRUE;
256   }
257
258   return FALSE;
259 }
260
261 FX_BOOL CJS_Value::ConvertToDate(CJS_Date& date) const {
262   //    if (GetType() == VT_date)
263   //    {
264   //            date = (double)(*this);
265   //            return TRUE;
266   //    }
267
268   if (IsDateObject()) {
269     date.Attach(m_pValue);
270     return TRUE;
271   }
272
273   return FALSE;
274 }
275
276 /* ---------------------------- CJS_PropValue ---------------------------- */
277
278 CJS_PropValue::CJS_PropValue(const CJS_Value& value)
279     : CJS_Value(value), m_bIsSetting(0) {}
280
281 CJS_PropValue::CJS_PropValue(v8::Isolate* isolate)
282     : CJS_Value(isolate), m_bIsSetting(0) {}
283
284 CJS_PropValue::~CJS_PropValue() {}
285
286 FX_BOOL CJS_PropValue::IsSetting() {
287   return m_bIsSetting;
288 }
289
290 FX_BOOL CJS_PropValue::IsGetting() {
291   return !m_bIsSetting;
292 }
293
294 void CJS_PropValue::operator<<(int iValue) {
295   ASSERT(!m_bIsSetting);
296   CJS_Value::operator=(iValue);
297 }
298
299 void CJS_PropValue::operator>>(int& iValue) const {
300   ASSERT(m_bIsSetting);
301   iValue = CJS_Value::ToInt();
302 }
303
304 void CJS_PropValue::operator<<(bool bValue) {
305   ASSERT(!m_bIsSetting);
306   CJS_Value::operator=(bValue);
307 }
308
309 void CJS_PropValue::operator>>(bool& bValue) const {
310   ASSERT(m_bIsSetting);
311   bValue = CJS_Value::ToBool();
312 }
313
314 void CJS_PropValue::operator<<(double dValue) {
315   ASSERT(!m_bIsSetting);
316   CJS_Value::operator=(dValue);
317 }
318
319 void CJS_PropValue::operator>>(double& dValue) const {
320   ASSERT(m_bIsSetting);
321   dValue = CJS_Value::ToDouble();
322 }
323
324 void CJS_PropValue::operator<<(CJS_Object* pObj) {
325   ASSERT(!m_bIsSetting);
326   CJS_Value::operator=(pObj);
327 }
328
329 void CJS_PropValue::operator>>(CJS_Object*& ppObj) const {
330   ASSERT(m_bIsSetting);
331   ppObj = CJS_Value::ToCJSObject();
332 }
333
334 void CJS_PropValue::operator<<(CJS_Document* pJsDoc) {
335   ASSERT(!m_bIsSetting);
336   CJS_Value::operator=(pJsDoc);
337 }
338
339 void CJS_PropValue::operator>>(CJS_Document*& ppJsDoc) const {
340   ASSERT(m_bIsSetting);
341   ppJsDoc = static_cast<CJS_Document*>(CJS_Value::ToCJSObject());
342 }
343
344 void CJS_PropValue::operator<<(v8::Local<v8::Object> pObj) {
345   ASSERT(!m_bIsSetting);
346   CJS_Value::operator=(pObj);
347 }
348
349 void CJS_PropValue::operator>>(v8::Local<v8::Object>& ppObj) const {
350   ASSERT(m_bIsSetting);
351   ppObj = CJS_Value::ToV8Object();
352 }
353
354 void CJS_PropValue::StartSetting() {
355   m_bIsSetting = 1;
356 }
357
358 void CJS_PropValue::StartGetting() {
359   m_bIsSetting = 0;
360 }
361 void CJS_PropValue::operator<<(CFX_ByteString string) {
362   ASSERT(!m_bIsSetting);
363   CJS_Value::operator=(string.c_str());
364 }
365
366 void CJS_PropValue::operator>>(CFX_ByteString& string) const {
367   ASSERT(m_bIsSetting);
368   string = CJS_Value::ToCFXByteString();
369 }
370
371 void CJS_PropValue::operator<<(const FX_WCHAR* c_string) {
372   ASSERT(!m_bIsSetting);
373   CJS_Value::operator=(c_string);
374 }
375
376 void CJS_PropValue::operator>>(CFX_WideString& wide_string) const {
377   ASSERT(m_bIsSetting);
378   wide_string = CJS_Value::ToCFXWideString();
379 }
380
381 void CJS_PropValue::operator<<(CFX_WideString wide_string) {
382   ASSERT(!m_bIsSetting);
383   CJS_Value::operator=(wide_string.c_str());
384 }
385
386 void CJS_PropValue::operator>>(CJS_Array& array) const {
387   ASSERT(m_bIsSetting);
388   ConvertToArray(array);
389 }
390
391 void CJS_PropValue::operator<<(CJS_Array& array) {
392   ASSERT(!m_bIsSetting);
393   CJS_Value::operator=(array);
394 }
395
396 void CJS_PropValue::operator>>(CJS_Date& date) const {
397   ASSERT(m_bIsSetting);
398   ConvertToDate(date);
399 }
400
401 void CJS_PropValue::operator<<(CJS_Date& date) {
402   ASSERT(!m_bIsSetting);
403   CJS_Value::operator=(date);
404 }
405
406 CJS_PropValue::operator v8::Local<v8::Value>() const {
407   return m_pValue;
408 }
409
410 /* ======================================== CJS_Array
411  * ========================================= */
412 CJS_Array::CJS_Array(v8::Isolate* isolate) : m_isolate(isolate) {}
413
414 CJS_Array::~CJS_Array() {}
415
416 void CJS_Array::Attach(v8::Local<v8::Array> pArray) {
417   m_pArray = pArray;
418 }
419
420 FX_BOOL CJS_Array::IsAttached() {
421   return FALSE;
422 }
423
424 void CJS_Array::GetElement(unsigned index, CJS_Value& value) {
425   if (m_pArray.IsEmpty())
426     return;
427   v8::Local<v8::Value> p = JS_GetArrayElement(m_isolate, m_pArray, index);
428   value.Attach(p, VT_object);
429 }
430
431 void CJS_Array::SetElement(unsigned index, CJS_Value value) {
432   if (m_pArray.IsEmpty())
433     m_pArray = JS_NewArray(m_isolate);
434
435   JS_PutArrayElement(m_isolate, m_pArray, index, value.ToV8Value(),
436                      value.GetType());
437 }
438
439 int CJS_Array::GetLength() {
440   if (m_pArray.IsEmpty())
441     return 0;
442   return JS_GetArrayLength(m_pArray);
443 }
444
445 CJS_Array::operator v8::Local<v8::Array>() {
446   if (m_pArray.IsEmpty())
447     m_pArray = JS_NewArray(m_isolate);
448
449   return m_pArray;
450 }
451
452 /* ======================================== CJS_Date
453  * ========================================= */
454
455 CJS_Date::CJS_Date(v8::Isolate* isolate) : m_isolate(isolate) {}
456
457 CJS_Date::CJS_Date(v8::Isolate* isolate, double dMsec_time) {
458   m_isolate = isolate;
459   m_pDate = JS_NewDate(isolate, dMsec_time);
460 }
461
462 CJS_Date::CJS_Date(v8::Isolate* isolate,
463                    int year,
464                    int mon,
465                    int day,
466                    int hour,
467                    int min,
468                    int sec) {
469   m_isolate = isolate;
470   m_pDate = JS_NewDate(isolate, MakeDate(year, mon, day, hour, min, sec, 0));
471 }
472
473 double CJS_Date::MakeDate(int year,
474                           int mon,
475                           int day,
476                           int hour,
477                           int min,
478                           int sec,
479                           int ms) {
480   return JS_MakeDate(JS_MakeDay(year, mon, day),
481                      JS_MakeTime(hour, min, sec, ms));
482 }
483
484 CJS_Date::~CJS_Date() {}
485
486 FX_BOOL CJS_Date::IsValidDate() {
487   if (m_pDate.IsEmpty())
488     return FALSE;
489   return !JS_PortIsNan(JS_ToNumber(m_isolate, m_pDate));
490 }
491
492 void CJS_Date::Attach(v8::Local<v8::Value> pDate) {
493   m_pDate = pDate;
494 }
495
496 int CJS_Date::GetYear() {
497   if (IsValidDate())
498     return JS_GetYearFromTime(JS_LocalTime(JS_ToNumber(m_isolate, m_pDate)));
499
500   return 0;
501 }
502
503 void CJS_Date::SetYear(int iYear) {
504   double date = MakeDate(iYear, GetMonth(), GetDay(), GetHours(), GetMinutes(),
505                          GetSeconds(), 0);
506   JS_ValueCopy(m_pDate, JS_NewDate(m_isolate, date));
507 }
508
509 int CJS_Date::GetMonth() {
510   if (IsValidDate())
511     return JS_GetMonthFromTime(JS_LocalTime(JS_ToNumber(m_isolate, m_pDate)));
512
513   return 0;
514 }
515
516 void CJS_Date::SetMonth(int iMonth) {
517   double date = MakeDate(GetYear(), iMonth, GetDay(), GetHours(), GetMinutes(),
518                          GetSeconds(), 0);
519   JS_ValueCopy(m_pDate, JS_NewDate(m_isolate, date));
520 }
521
522 int CJS_Date::GetDay() {
523   if (IsValidDate())
524     return JS_GetDayFromTime(JS_LocalTime(JS_ToNumber(m_isolate, 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   JS_ValueCopy(m_pDate, JS_NewDate(m_isolate, date));
533 }
534
535 int CJS_Date::GetHours() {
536   if (IsValidDate())
537     return JS_GetHourFromTime(JS_LocalTime(JS_ToNumber(m_isolate, m_pDate)));
538
539   return 0;
540 }
541
542 void CJS_Date::SetHours(int iHours) {
543   double date = MakeDate(GetYear(), GetMonth(), GetDay(), iHours, GetMinutes(),
544                          GetSeconds(), 0);
545   JS_ValueCopy(m_pDate, JS_NewDate(m_isolate, date));
546 }
547
548 int CJS_Date::GetMinutes() {
549   if (IsValidDate())
550     return JS_GetMinFromTime(JS_LocalTime(JS_ToNumber(m_isolate, m_pDate)));
551
552   return 0;
553 }
554
555 void CJS_Date::SetMinutes(int minutes) {
556   double date = MakeDate(GetYear(), GetMonth(), GetDay(), GetHours(), minutes,
557                          GetSeconds(), 0);
558   JS_ValueCopy(m_pDate, JS_NewDate(m_isolate, date));
559 }
560
561 int CJS_Date::GetSeconds() {
562   if (IsValidDate())
563     return JS_GetSecFromTime(JS_LocalTime(JS_ToNumber(m_isolate, m_pDate)));
564
565   return 0;
566 }
567
568 void CJS_Date::SetSeconds(int seconds) {
569   double date = MakeDate(GetYear(), GetMonth(), GetDay(), GetHours(),
570                          GetMinutes(), seconds, 0);
571   JS_ValueCopy(m_pDate, JS_NewDate(m_isolate, date));
572 }
573
574 CJS_Date::operator v8::Local<v8::Value>() {
575   return m_pDate;
576 }
577
578 CJS_Date::operator double() const {
579   if (m_pDate.IsEmpty())
580     return 0.0;
581   return JS_ToNumber(m_isolate, m_pDate);
582 }
583
584 CFX_WideString CJS_Date::ToString() const {
585   if (m_pDate.IsEmpty())
586     return L"";
587   return JS_ToString(m_isolate, m_pDate);
588 }