blob: 8f448a9d9e8c4b0a6a05bea9393c8cdc9bec1804 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclairf766ad22016-03-14 13:51:24 -04007#include "fpdfsdk/javascript/JS_Value.h"
Tom Sepez37458412015-10-06 11:33:46 -07008
Tom Sepez39bfe122015-09-17 15:25:23 -07009#include <time.h>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050010
Tom Sepezbd932572016-01-29 09:10:41 -080011#include <algorithm>
Tom Sepez39bfe122015-09-17 15:25:23 -070012#include <cmath>
13#include <limits>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050014#include <vector>
Tom Sepez39bfe122015-09-17 15:25:23 -070015
Dan Sinclairf766ad22016-03-14 13:51:24 -040016#include "fpdfsdk/javascript/Document.h"
17#include "fpdfsdk/javascript/JS_Define.h"
18#include "fpdfsdk/javascript/JS_Object.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070019
tsepezfbf52c22016-07-25 11:17:07 -070020namespace {
21
22const uint32_t g_nan[2] = {0, 0x7FF80000};
23
24double GetNan() {
Tom Sepez39bfe122015-09-17 15:25:23 -070025 return *(double*)g_nan;
26}
27
tsepezfbf52c22016-07-25 11:17:07 -070028double
29MakeDate(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
tsepezf3dc8c62016-08-10 06:29:29 -070036CJS_Value::CJS_Value(CJS_Runtime* pRuntime) {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -070037
tsepez40faa792016-07-15 17:58:02 -070038CJS_Value::CJS_Value(CJS_Runtime* pRuntime, v8::Local<v8::Value> pValue)
tsepezf3dc8c62016-08-10 06:29:29 -070039 : m_pValue(pValue) {}
Tom Sepez67fd5df2015-10-08 12:24:19 -070040
41CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const int& iValue)
tsepezf3dc8c62016-08-10 06:29:29 -070042 : m_pValue(FXJS_NewNumber(pRuntime->GetIsolate(), iValue)) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070043
Tom Sepez67fd5df2015-10-08 12:24:19 -070044CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const bool& bValue)
tsepezf3dc8c62016-08-10 06:29:29 -070045 : m_pValue(FXJS_NewBoolean(pRuntime->GetIsolate(), bValue)) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070046
Tom Sepez67fd5df2015-10-08 12:24:19 -070047CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const float& fValue)
tsepezf3dc8c62016-08-10 06:29:29 -070048 : m_pValue(FXJS_NewNumber(pRuntime->GetIsolate(), fValue)) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070049
Tom Sepez67fd5df2015-10-08 12:24:19 -070050CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const double& dValue)
tsepezf3dc8c62016-08-10 06:29:29 -070051 : m_pValue(FXJS_NewNumber(pRuntime->GetIsolate(), dValue)) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070052
tsepezf3dc8c62016-08-10 06:29:29 -070053CJS_Value::CJS_Value(CJS_Runtime* pRuntime, CJS_Object* pObj) {
54 if (pObj)
55 m_pValue = pObj->ToV8Object();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070056}
57
Tom Sepez67fd5df2015-10-08 12:24:19 -070058CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_WCHAR* pWstr)
tsepezf3dc8c62016-08-10 06:29:29 -070059 : m_pValue(FXJS_NewString(pRuntime->GetIsolate(), (wchar_t*)pWstr)) {}
Tom Sepezf79a69c2014-10-30 13:23:42 -070060
Tom Sepez67fd5df2015-10-08 12:24:19 -070061CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const FX_CHAR* pStr)
tsepezf3dc8c62016-08-10 06:29:29 -070062 : m_pValue(FXJS_NewString(pRuntime->GetIsolate(),
63 CFX_WideString::FromLocal(pStr).c_str())) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070064
tsepeze5aff742016-08-08 09:49:42 -070065CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const CJS_Array& array)
tsepezf3dc8c62016-08-10 06:29:29 -070066 : m_pValue(array.ToV8Array(pRuntime->GetIsolate())) {}
67
68CJS_Value::CJS_Value(CJS_Runtime* pRuntime, const CJS_Date& date)
69 : m_pValue(date.ToV8Date(pRuntime->GetIsolate())) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070070
Nico Weber9d8ec5a2015-08-04 13:00:21 -070071CJS_Value::~CJS_Value() {}
72
weili625ad662016-06-15 11:21:33 -070073CJS_Value::CJS_Value(const CJS_Value& other) = default;
74
tsepez40faa792016-07-15 17:58:02 -070075void CJS_Value::Attach(v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070076 m_pValue = pValue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070077}
78
Nico Weber9d8ec5a2015-08-04 13:00:21 -070079void CJS_Value::Detach() {
80 m_pValue = v8::Local<v8::Value>();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070081}
82
tsepezf3dc8c62016-08-10 06:29:29 -070083int CJS_Value::ToInt(v8::Isolate* pIsolate) const {
84 return FXJS_ToInt32(pIsolate, m_pValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070085}
86
tsepezf3dc8c62016-08-10 06:29:29 -070087bool CJS_Value::ToBool(v8::Isolate* pIsolate) const {
88 return FXJS_ToBoolean(pIsolate, m_pValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070089}
90
tsepezf3dc8c62016-08-10 06:29:29 -070091double CJS_Value::ToDouble(v8::Isolate* pIsolate) const {
92 return FXJS_ToNumber(pIsolate, m_pValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070093}
94
tsepezf3dc8c62016-08-10 06:29:29 -070095float CJS_Value::ToFloat(v8::Isolate* pIsolate) const {
96 return (float)ToDouble(pIsolate);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070097}
98
tsepezf3dc8c62016-08-10 06:29:29 -070099CJS_Object* CJS_Value::ToCJSObject(v8::Isolate* pIsolate) const {
100 v8::Local<v8::Object> pObj = FXJS_ToObject(pIsolate, m_pValue);
101 return (CJS_Object*)FXJS_GetPrivate(pIsolate, pObj);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700102}
103
tsepezf3dc8c62016-08-10 06:29:29 -0700104v8::Local<v8::Object> CJS_Value::ToV8Object(v8::Isolate* pIsolate) const {
105 return FXJS_ToObject(pIsolate, m_pValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700106}
107
tsepezf3dc8c62016-08-10 06:29:29 -0700108CFX_WideString CJS_Value::ToCFXWideString(v8::Isolate* pIsolate) const {
109 return FXJS_ToString(pIsolate, m_pValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700110}
111
tsepezf3dc8c62016-08-10 06:29:29 -0700112CFX_ByteString CJS_Value::ToCFXByteString(v8::Isolate* pIsolate) const {
113 return CFX_ByteString::FromUnicode(ToCFXWideString(pIsolate));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700114}
115
tsepezf3dc8c62016-08-10 06:29:29 -0700116v8::Local<v8::Value> CJS_Value::ToV8Value(v8::Isolate* pIsolate) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700117 return m_pValue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700118}
119
tsepezf3dc8c62016-08-10 06:29:29 -0700120v8::Local<v8::Array> CJS_Value::ToV8Array(v8::Isolate* pIsolate) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700121 if (IsArrayObject())
tsepezf3dc8c62016-08-10 06:29:29 -0700122 return v8::Local<v8::Array>::Cast(FXJS_ToObject(pIsolate, m_pValue));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700123 return v8::Local<v8::Array>();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700124}
125
tsepezf3dc8c62016-08-10 06:29:29 -0700126void CJS_Value::SetNull(CJS_Runtime* pRuntime) {
127 m_pValue = FXJS_NewNull(pRuntime->GetIsolate());
128}
129
130void CJS_Value::MaybeCoerceToNumber(v8::Isolate* pIsolate) {
Tom Sepez4246b002016-01-20 11:48:29 -0800131 bool bAllowNaN = false;
tsepez40faa792016-07-15 17:58:02 -0700132 if (GetType() == VT_string) {
tsepezf3dc8c62016-08-10 06:29:29 -0700133 CFX_ByteString bstr = ToCFXByteString(pIsolate);
Tom Sepez4246b002016-01-20 11:48:29 -0800134 if (bstr.GetLength() == 0)
135 return;
136 if (bstr == "NaN")
137 bAllowNaN = true;
138 }
tsepezf3dc8c62016-08-10 06:29:29 -0700139 v8::TryCatch try_catch(pIsolate);
Tom Sepez4246b002016-01-20 11:48:29 -0800140 v8::MaybeLocal<v8::Number> maybeNum =
tsepezf3dc8c62016-08-10 06:29:29 -0700141 m_pValue->ToNumber(pIsolate->GetCurrentContext());
Tom Sepez4246b002016-01-20 11:48:29 -0800142 if (maybeNum.IsEmpty())
143 return;
144 v8::Local<v8::Number> num = maybeNum.ToLocalChecked();
145 if (std::isnan(num->Value()) && !bAllowNaN)
146 return;
147 m_pValue = num;
Tom Sepez4246b002016-01-20 11:48:29 -0800148}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700149
tsepez40faa792016-07-15 17:58:02 -0700150// static
151CJS_Value::Type CJS_Value::GetValueType(v8::Local<v8::Value> value) {
152 if (value.IsEmpty())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700153 return VT_unknown;
tsepez40faa792016-07-15 17:58:02 -0700154 if (value->IsString())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700155 return VT_string;
tsepez40faa792016-07-15 17:58:02 -0700156 if (value->IsNumber())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700157 return VT_number;
tsepez40faa792016-07-15 17:58:02 -0700158 if (value->IsBoolean())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700159 return VT_boolean;
tsepez40faa792016-07-15 17:58:02 -0700160 if (value->IsDate())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700161 return VT_date;
tsepez40faa792016-07-15 17:58:02 -0700162 if (value->IsObject())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700163 return VT_object;
tsepez40faa792016-07-15 17:58:02 -0700164 if (value->IsNull())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700165 return VT_null;
tsepez40faa792016-07-15 17:58:02 -0700166 if (value->IsUndefined())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700167 return VT_undefined;
168 return VT_unknown;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700169}
170
tsepezf3dc8c62016-08-10 06:29:29 -0700171bool CJS_Value::IsArrayObject() const {
172 return !m_pValue.IsEmpty() && m_pValue->IsArray();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700173}
174
tsepezf3dc8c62016-08-10 06:29:29 -0700175bool CJS_Value::IsDateObject() const {
176 return !m_pValue.IsEmpty() && m_pValue->IsDate();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700177}
178
tsepezf3dc8c62016-08-10 06:29:29 -0700179bool CJS_Value::ConvertToArray(v8::Isolate* pIsolate, CJS_Array& array) const {
180 if (!IsArrayObject())
181 return false;
182 array.Attach(FXJS_ToArray(pIsolate, m_pValue));
183 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700184}
185
tsepezf3dc8c62016-08-10 06:29:29 -0700186bool CJS_Value::ConvertToDate(v8::Isolate* pIsolate, CJS_Date& date) const {
187 if (!IsDateObject())
188 return false;
189 v8::Local<v8::Value> mutable_value = m_pValue;
190 date.Attach(mutable_value.As<v8::Date>());
191 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700192}
193
Tom Sepez67fd5df2015-10-08 12:24:19 -0700194CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime)
tsepezf3dc8c62016-08-10 06:29:29 -0700195 : m_bIsSetting(0), m_Value(pRuntime), m_pJSRuntime(pRuntime) {}
196
197CJS_PropValue::CJS_PropValue(CJS_Runtime* pRuntime, const CJS_Value& value)
198 : m_bIsSetting(0), m_Value(value), m_pJSRuntime(pRuntime) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700199
Dan Sinclairf766ad22016-03-14 13:51:24 -0400200CJS_PropValue::~CJS_PropValue() {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700201
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202void CJS_PropValue::operator<<(int iValue) {
203 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700204 m_Value = CJS_Value(m_pJSRuntime, iValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700205}
206
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207void CJS_PropValue::operator>>(int& iValue) const {
208 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700209 iValue = m_Value.ToInt(m_pJSRuntime->GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700210}
211
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700212void CJS_PropValue::operator<<(bool bValue) {
213 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700214 m_Value = CJS_Value(m_pJSRuntime, bValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700215}
216
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700217void CJS_PropValue::operator>>(bool& bValue) const {
218 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700219 bValue = m_Value.ToBool(m_pJSRuntime->GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700220}
221
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700222void CJS_PropValue::operator<<(double dValue) {
223 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700224 m_Value = CJS_Value(m_pJSRuntime, dValue);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700225}
226
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227void CJS_PropValue::operator>>(double& dValue) const {
228 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700229 dValue = m_Value.ToDouble(m_pJSRuntime->GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700230}
231
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232void CJS_PropValue::operator<<(CJS_Object* pObj) {
233 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700234 m_Value = CJS_Value(m_pJSRuntime, pObj);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700235}
236
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700237void CJS_PropValue::operator>>(CJS_Object*& ppObj) const {
238 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700239 ppObj = m_Value.ToCJSObject(m_pJSRuntime->GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700240}
241
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700242void CJS_PropValue::operator<<(CJS_Document* pJsDoc) {
243 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700244 m_Value = CJS_Value(m_pJSRuntime, pJsDoc);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700245}
246
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700247void CJS_PropValue::operator>>(CJS_Document*& ppJsDoc) const {
248 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700249 ppJsDoc = static_cast<CJS_Document*>(
250 m_Value.ToCJSObject(m_pJSRuntime->GetIsolate()));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700251}
252
Tom Sepez808a99e2015-09-10 12:28:37 -0700253void CJS_PropValue::operator<<(v8::Local<v8::Object> pObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700254 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700255 m_Value = CJS_Value(m_pJSRuntime, pObj);
JUN FANG33f6f0d2015-04-06 12:39:51 -0700256}
257
Tom Sepez808a99e2015-09-10 12:28:37 -0700258void CJS_PropValue::operator>>(v8::Local<v8::Object>& ppObj) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700260 ppObj = m_Value.ToV8Object(m_pJSRuntime->GetIsolate());
JUN FANG33f6f0d2015-04-06 12:39:51 -0700261}
262
Dan Sinclair3ebd1212016-03-09 09:59:23 -0500263void CJS_PropValue::operator<<(CFX_ByteString str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700264 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700265 m_Value = CJS_Value(m_pJSRuntime, str.c_str());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700266}
267
Dan Sinclair3ebd1212016-03-09 09:59:23 -0500268void CJS_PropValue::operator>>(CFX_ByteString& str) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700269 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700270 str = m_Value.ToCFXByteString(m_pJSRuntime->GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700271}
272
tsepezf3dc8c62016-08-10 06:29:29 -0700273void CJS_PropValue::operator<<(const FX_WCHAR* str) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700274 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700275 m_Value = CJS_Value(m_pJSRuntime, str);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700276}
277
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278void CJS_PropValue::operator>>(CFX_WideString& wide_string) const {
279 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700280 wide_string = m_Value.ToCFXWideString(m_pJSRuntime->GetIsolate());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700281}
282
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700283void CJS_PropValue::operator<<(CFX_WideString wide_string) {
284 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700285 m_Value = CJS_Value(m_pJSRuntime, wide_string.c_str());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700286}
287
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700288void CJS_PropValue::operator>>(CJS_Array& array) const {
289 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700290 m_Value.ConvertToArray(m_pJSRuntime->GetIsolate(), array);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700291}
292
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700293void CJS_PropValue::operator<<(CJS_Array& array) {
294 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700295 m_Value =
296 CJS_Value(m_pJSRuntime, array.ToV8Array(m_pJSRuntime->GetIsolate()));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700297}
298
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700299void CJS_PropValue::operator>>(CJS_Date& date) const {
300 ASSERT(m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700301 m_Value.ConvertToDate(m_pJSRuntime->GetIsolate(), date);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700302}
303
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700304void CJS_PropValue::operator<<(CJS_Date& date) {
305 ASSERT(!m_bIsSetting);
tsepezf3dc8c62016-08-10 06:29:29 -0700306 m_Value = CJS_Value(m_pJSRuntime, date);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700307}
308
tsepeze5aff742016-08-08 09:49:42 -0700309CJS_Array::CJS_Array() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700310
weili625ad662016-06-15 11:21:33 -0700311CJS_Array::CJS_Array(const CJS_Array& other) = default;
312
tsepeze5aff742016-08-08 09:49:42 -0700313CJS_Array::~CJS_Array() {}
314
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700315void CJS_Array::Attach(v8::Local<v8::Array> pArray) {
316 m_pArray = pArray;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700317}
318
tsepeze5aff742016-08-08 09:49:42 -0700319void CJS_Array::GetElement(v8::Isolate* pIsolate,
320 unsigned index,
321 CJS_Value& value) const {
322 if (!m_pArray.IsEmpty())
323 value.Attach(FXJS_GetArrayElement(pIsolate, m_pArray, index));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700324}
325
tsepeze5aff742016-08-08 09:49:42 -0700326void CJS_Array::SetElement(v8::Isolate* pIsolate,
327 unsigned index,
328 const CJS_Value& value) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700329 if (m_pArray.IsEmpty())
tsepeze5aff742016-08-08 09:49:42 -0700330 m_pArray = FXJS_NewArray(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700331
tsepezf3dc8c62016-08-10 06:29:29 -0700332 FXJS_PutArrayElement(pIsolate, m_pArray, index, value.ToV8Value(pIsolate));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700333}
334
tsepezfbf52c22016-07-25 11:17:07 -0700335int CJS_Array::GetLength() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700336 if (m_pArray.IsEmpty())
337 return 0;
Tom Sepez39bfe122015-09-17 15:25:23 -0700338 return FXJS_GetArrayLength(m_pArray);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700339}
340
tsepeze5aff742016-08-08 09:49:42 -0700341v8::Local<v8::Array> CJS_Array::ToV8Array(v8::Isolate* pIsolate) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700342 if (m_pArray.IsEmpty())
tsepeze5aff742016-08-08 09:49:42 -0700343 m_pArray = FXJS_NewArray(pIsolate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700344
345 return m_pArray;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700346}
347
tsepezf3c88322016-08-09 07:30:38 -0700348CJS_Date::CJS_Date() {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700349
tsepezf3c88322016-08-09 07:30:38 -0700350CJS_Date::CJS_Date(v8::Isolate* pIsolate, double dMsecTime)
351 : m_pDate(FXJS_NewDate(pIsolate, dMsecTime)) {}
Tom Sepez67fd5df2015-10-08 12:24:19 -0700352
tsepezf3c88322016-08-09 07:30:38 -0700353CJS_Date::CJS_Date(v8::Isolate* pIsolate,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700354 int year,
355 int mon,
356 int day,
357 int hour,
358 int min,
Tom Sepez67fd5df2015-10-08 12:24:19 -0700359 int sec)
tsepezf3c88322016-08-09 07:30:38 -0700360 : m_pDate(FXJS_NewDate(pIsolate,
361 MakeDate(year, mon, day, hour, min, sec, 0))) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700362
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363CJS_Date::~CJS_Date() {}
364
tsepezf3c88322016-08-09 07:30:38 -0700365bool CJS_Date::IsValidDate(v8::Isolate* pIsolate) const {
366 return !m_pDate.IsEmpty() && !JS_PortIsNan(FXJS_ToNumber(pIsolate, m_pDate));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700367}
368
tsepez135b9982016-08-05 09:32:50 -0700369void CJS_Date::Attach(v8::Local<v8::Date> pDate) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 m_pDate = pDate;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700371}
372
tsepezf3c88322016-08-09 07:30:38 -0700373int CJS_Date::GetYear(v8::Isolate* pIsolate) const {
374 if (!IsValidDate(pIsolate))
tsepezfbf52c22016-07-25 11:17:07 -0700375 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700376
tsepezf3c88322016-08-09 07:30:38 -0700377 return JS_GetYearFromTime(JS_LocalTime(FXJS_ToNumber(pIsolate, m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700378}
379
tsepezf3c88322016-08-09 07:30:38 -0700380void CJS_Date::SetYear(v8::Isolate* pIsolate, int iYear) {
381 m_pDate = FXJS_NewDate(
382 pIsolate,
383 MakeDate(iYear, GetMonth(pIsolate), GetDay(pIsolate), GetHours(pIsolate),
384 GetMinutes(pIsolate), GetSeconds(pIsolate), 0));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700385}
386
tsepezf3c88322016-08-09 07:30:38 -0700387int CJS_Date::GetMonth(v8::Isolate* pIsolate) const {
388 if (!IsValidDate(pIsolate))
tsepezfbf52c22016-07-25 11:17:07 -0700389 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700390
tsepezf3c88322016-08-09 07:30:38 -0700391 return JS_GetMonthFromTime(JS_LocalTime(FXJS_ToNumber(pIsolate, m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700392}
393
tsepezf3c88322016-08-09 07:30:38 -0700394void CJS_Date::SetMonth(v8::Isolate* pIsolate, int iMonth) {
395 m_pDate = FXJS_NewDate(
396 pIsolate,
397 MakeDate(GetYear(pIsolate), iMonth, GetDay(pIsolate), GetHours(pIsolate),
398 GetMinutes(pIsolate), GetSeconds(pIsolate), 0));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700399}
400
tsepezf3c88322016-08-09 07:30:38 -0700401int CJS_Date::GetDay(v8::Isolate* pIsolate) const {
402 if (!IsValidDate(pIsolate))
tsepezfbf52c22016-07-25 11:17:07 -0700403 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700404
tsepezf3c88322016-08-09 07:30:38 -0700405 return JS_GetDayFromTime(JS_LocalTime(FXJS_ToNumber(pIsolate, m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700406}
407
tsepezf3c88322016-08-09 07:30:38 -0700408void CJS_Date::SetDay(v8::Isolate* pIsolate, int iDay) {
409 m_pDate = FXJS_NewDate(
410 pIsolate,
411 MakeDate(GetYear(pIsolate), GetMonth(pIsolate), iDay, GetHours(pIsolate),
412 GetMinutes(pIsolate), GetSeconds(pIsolate), 0));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700413}
414
tsepezf3c88322016-08-09 07:30:38 -0700415int CJS_Date::GetHours(v8::Isolate* pIsolate) const {
416 if (!IsValidDate(pIsolate))
tsepezfbf52c22016-07-25 11:17:07 -0700417 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700418
tsepezf3c88322016-08-09 07:30:38 -0700419 return JS_GetHourFromTime(JS_LocalTime(FXJS_ToNumber(pIsolate, m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700420}
421
tsepezf3c88322016-08-09 07:30:38 -0700422void CJS_Date::SetHours(v8::Isolate* pIsolate, int iHours) {
423 m_pDate = FXJS_NewDate(
424 pIsolate,
425 MakeDate(GetYear(pIsolate), GetMonth(pIsolate), GetDay(pIsolate), iHours,
426 GetMinutes(pIsolate), GetSeconds(pIsolate), 0));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700427}
428
tsepezf3c88322016-08-09 07:30:38 -0700429int CJS_Date::GetMinutes(v8::Isolate* pIsolate) const {
430 if (!IsValidDate(pIsolate))
tsepezfbf52c22016-07-25 11:17:07 -0700431 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700432
tsepezf3c88322016-08-09 07:30:38 -0700433 return JS_GetMinFromTime(JS_LocalTime(FXJS_ToNumber(pIsolate, m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700434}
435
tsepezf3c88322016-08-09 07:30:38 -0700436void CJS_Date::SetMinutes(v8::Isolate* pIsolate, int minutes) {
437 m_pDate =
438 FXJS_NewDate(pIsolate, MakeDate(GetYear(pIsolate), GetMonth(pIsolate),
439 GetDay(pIsolate), GetHours(pIsolate),
440 minutes, GetSeconds(pIsolate), 0));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700441}
442
tsepezf3c88322016-08-09 07:30:38 -0700443int CJS_Date::GetSeconds(v8::Isolate* pIsolate) const {
444 if (!IsValidDate(pIsolate))
tsepezfbf52c22016-07-25 11:17:07 -0700445 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700446
tsepezf3c88322016-08-09 07:30:38 -0700447 return JS_GetSecFromTime(JS_LocalTime(FXJS_ToNumber(pIsolate, m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700448}
449
tsepezf3c88322016-08-09 07:30:38 -0700450void CJS_Date::SetSeconds(v8::Isolate* pIsolate, int seconds) {
451 m_pDate =
452 FXJS_NewDate(pIsolate, MakeDate(GetYear(pIsolate), GetMonth(pIsolate),
453 GetDay(pIsolate), GetHours(pIsolate),
454 GetMinutes(pIsolate), seconds, 0));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700455}
456
tsepezf3c88322016-08-09 07:30:38 -0700457double CJS_Date::ToDouble(v8::Isolate* pIsolate) const {
458 return !m_pDate.IsEmpty() ? FXJS_ToNumber(pIsolate, m_pDate) : 0.0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700459}
460
tsepezf3c88322016-08-09 07:30:38 -0700461CFX_WideString CJS_Date::ToString(v8::Isolate* pIsolate) const {
462 return !m_pDate.IsEmpty() ? FXJS_ToString(pIsolate, m_pDate)
463 : CFX_WideString();
464}
tsepezfbf52c22016-07-25 11:17:07 -0700465
tsepezf3c88322016-08-09 07:30:38 -0700466v8::Local<v8::Date> CJS_Date::ToV8Date(v8::Isolate* pIsolate) const {
467 return m_pDate;
Tom Sepez39bfe122015-09-17 15:25:23 -0700468}
469
470double _getLocalTZA() {
471 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
472 return 0;
473 time_t t = 0;
474 time(&t);
475 localtime(&t);
476#if _MSC_VER >= 1900
477 // In gcc and in Visual Studio prior to VS 2015 'timezone' is a global
478 // variable declared in time.h. That variable was deprecated and in VS 2015
479 // is removed, with _get_timezone replacing it.
480 long timezone = 0;
481 _get_timezone(&timezone);
482#endif
483 return (double)(-(timezone * 1000));
484}
485
486int _getDaylightSavingTA(double d) {
487 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
488 return 0;
489 time_t t = (time_t)(d / 1000);
490 struct tm* tmp = localtime(&t);
Lei Zhang412e9082015-12-14 18:34:00 -0800491 if (!tmp)
Tom Sepez39bfe122015-09-17 15:25:23 -0700492 return 0;
493 if (tmp->tm_isdst > 0)
494 // One hour.
495 return (int)60 * 60 * 1000;
496 return 0;
497}
498
499double _Mod(double x, double y) {
500 double r = fmod(x, y);
501 if (r < 0)
502 r += y;
503 return r;
504}
505
506int _isfinite(double v) {
507#if _MSC_VER
508 return ::_finite(v);
509#else
510 return std::fabs(v) < std::numeric_limits<double>::max();
511#endif
512}
513
514double _toInteger(double n) {
515 return (n >= 0) ? FXSYS_floor(n) : -FXSYS_floor(-n);
516}
517
518bool _isLeapYear(int year) {
519 return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0));
520}
521
522int _DayFromYear(int y) {
523 return (int)(365 * (y - 1970.0) + FXSYS_floor((y - 1969.0) / 4) -
524 FXSYS_floor((y - 1901.0) / 100) +
525 FXSYS_floor((y - 1601.0) / 400));
526}
527
528double _TimeFromYear(int y) {
Lei Zhang1ac47eb2015-12-21 11:04:44 -0800529 return 86400000.0 * _DayFromYear(y);
Tom Sepez39bfe122015-09-17 15:25:23 -0700530}
531
Tom Sepez4161c5c2016-03-21 12:26:54 -0700532static const uint16_t daysMonth[12] = {0, 31, 59, 90, 120, 151,
533 181, 212, 243, 273, 304, 334};
534static const uint16_t leapDaysMonth[12] = {0, 31, 60, 91, 121, 152,
535 182, 213, 244, 274, 305, 335};
536
Tom Sepez39bfe122015-09-17 15:25:23 -0700537double _TimeFromYearMonth(int y, int m) {
Tom Sepez4161c5c2016-03-21 12:26:54 -0700538 const uint16_t* pMonth = _isLeapYear(y) ? leapDaysMonth : daysMonth;
Tom Sepez39bfe122015-09-17 15:25:23 -0700539 return _TimeFromYear(y) + ((double)pMonth[m]) * 86400000;
540}
541
542int _Day(double t) {
543 return (int)FXSYS_floor(t / 86400000);
544}
545
546int _YearFromTime(double t) {
547 // estimate the time.
Lei Zhang1ac47eb2015-12-21 11:04:44 -0800548 int y = 1970 + static_cast<int>(t / (365.2425 * 86400000));
Tom Sepez39bfe122015-09-17 15:25:23 -0700549 if (_TimeFromYear(y) <= t) {
550 while (_TimeFromYear(y + 1) <= t)
551 y++;
Dan Sinclair738b08c2016-03-01 14:45:20 -0500552 } else {
Lei Zhang1ac47eb2015-12-21 11:04:44 -0800553 while (_TimeFromYear(y) > t)
Tom Sepez39bfe122015-09-17 15:25:23 -0700554 y--;
Dan Sinclair738b08c2016-03-01 14:45:20 -0500555 }
Tom Sepez39bfe122015-09-17 15:25:23 -0700556 return y;
557}
558
559int _DayWithinYear(double t) {
560 int year = _YearFromTime(t);
561 int day = _Day(t);
562 return day - _DayFromYear(year);
563}
564
565int _MonthFromTime(double t) {
566 int day = _DayWithinYear(t);
567 int year = _YearFromTime(t);
568 if (0 <= day && day < 31)
569 return 0;
570 if (31 <= day && day < 59 + _isLeapYear(year))
571 return 1;
572 if ((59 + _isLeapYear(year)) <= day && day < (90 + _isLeapYear(year)))
573 return 2;
574 if ((90 + _isLeapYear(year)) <= day && day < (120 + _isLeapYear(year)))
575 return 3;
576 if ((120 + _isLeapYear(year)) <= day && day < (151 + _isLeapYear(year)))
577 return 4;
578 if ((151 + _isLeapYear(year)) <= day && day < (181 + _isLeapYear(year)))
579 return 5;
580 if ((181 + _isLeapYear(year)) <= day && day < (212 + _isLeapYear(year)))
581 return 6;
582 if ((212 + _isLeapYear(year)) <= day && day < (243 + _isLeapYear(year)))
583 return 7;
584 if ((243 + _isLeapYear(year)) <= day && day < (273 + _isLeapYear(year)))
585 return 8;
586 if ((273 + _isLeapYear(year)) <= day && day < (304 + _isLeapYear(year)))
587 return 9;
588 if ((304 + _isLeapYear(year)) <= day && day < (334 + _isLeapYear(year)))
589 return 10;
590 if ((334 + _isLeapYear(year)) <= day && day < (365 + _isLeapYear(year)))
591 return 11;
592
593 return -1;
594}
595
596int _DateFromTime(double t) {
597 int day = _DayWithinYear(t);
598 int year = _YearFromTime(t);
weili12367cb2016-06-03 11:22:16 -0700599 int leap = _isLeapYear(year);
Tom Sepez39bfe122015-09-17 15:25:23 -0700600 int month = _MonthFromTime(t);
601 switch (month) {
602 case 0:
603 return day + 1;
604 case 1:
605 return day - 30;
606 case 2:
607 return day - 58 - leap;
608 case 3:
609 return day - 89 - leap;
610 case 4:
611 return day - 119 - leap;
612 case 5:
613 return day - 150 - leap;
614 case 6:
615 return day - 180 - leap;
616 case 7:
617 return day - 211 - leap;
618 case 8:
619 return day - 242 - leap;
620 case 9:
621 return day - 272 - leap;
622 case 10:
623 return day - 303 - leap;
624 case 11:
625 return day - 333 - leap;
626 default:
627 return 0;
628 }
629}
630
631double JS_GetDateTime() {
632 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
633 return 0;
thestig1cd352e2016-06-07 17:53:06 -0700634 time_t t = time(nullptr);
Tom Sepez39bfe122015-09-17 15:25:23 -0700635 struct tm* pTm = localtime(&t);
636
637 int year = pTm->tm_year + 1900;
638 double t1 = _TimeFromYear(year);
639
640 return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 +
641 pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0;
642}
643
644int JS_GetYearFromTime(double dt) {
645 return _YearFromTime(dt);
646}
647
648int JS_GetMonthFromTime(double dt) {
649 return _MonthFromTime(dt);
650}
651
652int JS_GetDayFromTime(double dt) {
653 return _DateFromTime(dt);
654}
655
656int JS_GetHourFromTime(double dt) {
tsepez86a61dc2016-03-25 10:00:11 -0700657 return (int)_Mod(floor(dt / (60 * 60 * 1000)), 24);
Tom Sepez39bfe122015-09-17 15:25:23 -0700658}
659
660int JS_GetMinFromTime(double dt) {
tsepez86a61dc2016-03-25 10:00:11 -0700661 return (int)_Mod(floor(dt / (60 * 1000)), 60);
Tom Sepez39bfe122015-09-17 15:25:23 -0700662}
663
664int JS_GetSecFromTime(double dt) {
tsepez86a61dc2016-03-25 10:00:11 -0700665 return (int)_Mod(floor(dt / 1000), 60);
Tom Sepez39bfe122015-09-17 15:25:23 -0700666}
667
tsepez018935c2016-04-15 13:15:12 -0700668double JS_DateParse(const CFX_WideString& str) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700669 v8::Isolate* pIsolate = v8::Isolate::GetCurrent();
670 v8::Isolate::Scope isolate_scope(pIsolate);
671 v8::HandleScope scope(pIsolate);
672
673 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
674
675 // Use the built-in object method.
676 v8::Local<v8::Value> v =
677 context->Global()
678 ->Get(context, v8::String::NewFromUtf8(pIsolate, "Date",
679 v8::NewStringType::kNormal)
680 .ToLocalChecked())
681 .ToLocalChecked();
682 if (v->IsObject()) {
683 v8::Local<v8::Object> o = v->ToObject(context).ToLocalChecked();
684 v = o->Get(context, v8::String::NewFromUtf8(pIsolate, "parse",
685 v8::NewStringType::kNormal)
Dan Sinclairf766ad22016-03-14 13:51:24 -0400686 .ToLocalChecked())
687 .ToLocalChecked();
Tom Sepez39bfe122015-09-17 15:25:23 -0700688 if (v->IsFunction()) {
689 v8::Local<v8::Function> funC = v8::Local<v8::Function>::Cast(v);
Tom Sepez39bfe122015-09-17 15:25:23 -0700690 const int argc = 1;
Dan Sinclair3ebd1212016-03-09 09:59:23 -0500691 v8::Local<v8::String> timeStr = FXJS_WSToJSString(pIsolate, str);
Tom Sepez39bfe122015-09-17 15:25:23 -0700692 v8::Local<v8::Value> argv[argc] = {timeStr};
693 v = funC->Call(context, context->Global(), argc, argv).ToLocalChecked();
694 if (v->IsNumber()) {
695 double date = v->ToNumber(context).ToLocalChecked()->Value();
696 if (!_isfinite(date))
697 return date;
tsepez86a61dc2016-03-25 10:00:11 -0700698 return JS_LocalTime(date);
Tom Sepez39bfe122015-09-17 15:25:23 -0700699 }
700 }
701 }
702 return 0;
703}
704
705double JS_MakeDay(int nYear, int nMonth, int nDate) {
706 if (!_isfinite(nYear) || !_isfinite(nMonth) || !_isfinite(nDate))
707 return GetNan();
708 double y = _toInteger(nYear);
709 double m = _toInteger(nMonth);
710 double dt = _toInteger(nDate);
711 double ym = y + FXSYS_floor((double)m / 12);
712 double mn = _Mod(m, 12);
713
714 double t = _TimeFromYearMonth((int)ym, (int)mn);
715
716 if (_YearFromTime(t) != ym || _MonthFromTime(t) != mn ||
717 _DateFromTime(t) != 1)
718 return GetNan();
719 return _Day(t) + dt - 1;
720}
721
722double JS_MakeTime(int nHour, int nMin, int nSec, int nMs) {
723 if (!_isfinite(nHour) || !_isfinite(nMin) || !_isfinite(nSec) ||
724 !_isfinite(nMs))
725 return GetNan();
726
727 double h = _toInteger(nHour);
728 double m = _toInteger(nMin);
729 double s = _toInteger(nSec);
730 double milli = _toInteger(nMs);
731
732 return h * 3600000 + m * 60000 + s * 1000 + milli;
733}
734
735double JS_MakeDate(double day, double time) {
736 if (!_isfinite(day) || !_isfinite(time))
737 return GetNan();
738
739 return day * 86400000 + time;
740}
741
742bool JS_PortIsNan(double d) {
743 return d != d;
744}
745
746double JS_LocalTime(double d) {
tsepez86a61dc2016-03-25 10:00:11 -0700747 return d + _getLocalTZA() + _getDaylightSavingTA(d);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700748}
Tom Sepezbd932572016-01-29 09:10:41 -0800749
750std::vector<CJS_Value> JS_ExpandKeywordParams(
751 CJS_Runtime* pRuntime,
752 const std::vector<CJS_Value>& originals,
753 size_t nKeywords,
754 ...) {
755 ASSERT(nKeywords);
756
757 std::vector<CJS_Value> result(nKeywords, CJS_Value(pRuntime));
758 size_t size = std::min(originals.size(), nKeywords);
759 for (size_t i = 0; i < size; ++i)
760 result[i] = originals[i];
761
762 if (originals.size() != 1 || originals[0].GetType() != CJS_Value::VT_object ||
763 originals[0].IsArrayObject()) {
764 return result;
765 }
tsepezf3dc8c62016-08-10 06:29:29 -0700766 v8::Local<v8::Object> pObj = originals[0].ToV8Object(pRuntime->GetIsolate());
Tom Sepezbd932572016-01-29 09:10:41 -0800767 result[0] = CJS_Value(pRuntime); // Make unknown.
768
769 va_list ap;
770 va_start(ap, nKeywords);
Wei Li89409932016-03-28 10:33:33 -0700771 for (size_t i = 0; i < nKeywords; ++i) {
Tom Sepezbd932572016-01-29 09:10:41 -0800772 const wchar_t* property = va_arg(ap, const wchar_t*);
773 v8::Local<v8::Value> v8Value =
774 FXJS_GetObjectElement(pRuntime->GetIsolate(), pObj, property);
775 if (!v8Value->IsUndefined())
tsepez40faa792016-07-15 17:58:02 -0700776 result[i] = CJS_Value(pRuntime, v8Value);
Tom Sepezbd932572016-01-29 09:10:41 -0800777 }
778 va_end(ap);
779 return result;
780}