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