blob: a8b6ad6bcd8bf26e500df8424a65cdc026fd720e [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
tsepezfbf52c22016-07-25 11:17:07 -070022double
23MakeDate(int year, int mon, int day, int hour, int min, int sec, int ms) {
24 return JS_MakeDate(JS_MakeDay(year, mon, day),
25 JS_MakeTime(hour, min, sec, ms));
26}
27
Lei Zhangab5939e2017-06-16 02:23:18 -070028double GetLocalTZA() {
29 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
30 return 0;
31 time_t t = 0;
32 time(&t);
33 localtime(&t);
Dan Sinclair698aed72017-09-26 16:24:49 -040034#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
Tom Sepeza2da7c52017-08-03 13:34:08 -070035 // In gcc 'timezone' is a global variable declared in time.h. In VC++, that
36 // variable was removed in VC++ 2015, with _get_timezone replacing it.
Lei Zhangab5939e2017-06-16 02:23:18 -070037 long timezone = 0;
38 _get_timezone(&timezone);
Dan Sinclair698aed72017-09-26 16:24:49 -040039#endif // _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
Lei Zhangab5939e2017-06-16 02:23:18 -070040 return (double)(-(timezone * 1000));
41}
42
43int GetDaylightSavingTA(double d) {
44 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
45 return 0;
46 time_t t = (time_t)(d / 1000);
47 struct tm* tmp = localtime(&t);
48 if (!tmp)
49 return 0;
50 if (tmp->tm_isdst > 0)
51 // One hour.
52 return (int)60 * 60 * 1000;
53 return 0;
54}
55
56double Mod(double x, double y) {
57 double r = fmod(x, y);
58 if (r < 0)
59 r += y;
60 return r;
61}
62
Lei Zhangab5939e2017-06-16 02:23:18 -070063bool IsLeapYear(int year) {
64 return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 != 0));
65}
66
67int DayFromYear(int y) {
68 return (int)(365 * (y - 1970.0) + floor((y - 1969.0) / 4) -
69 floor((y - 1901.0) / 100) + floor((y - 1601.0) / 400));
70}
71
72double TimeFromYear(int y) {
73 return 86400000.0 * DayFromYear(y);
74}
75
76static const uint16_t daysMonth[12] = {0, 31, 59, 90, 120, 151,
77 181, 212, 243, 273, 304, 334};
78static const uint16_t leapDaysMonth[12] = {0, 31, 60, 91, 121, 152,
79 182, 213, 244, 274, 305, 335};
80
81double TimeFromYearMonth(int y, int m) {
82 const uint16_t* pMonth = IsLeapYear(y) ? leapDaysMonth : daysMonth;
83 return TimeFromYear(y) + ((double)pMonth[m]) * 86400000;
84}
85
86int Day(double t) {
Tom Sepezdf950b82017-08-04 11:33:49 -070087 return static_cast<int>(floor(t / 86400000.0));
Lei Zhangab5939e2017-06-16 02:23:18 -070088}
89
90int YearFromTime(double t) {
91 // estimate the time.
Tom Sepezdf950b82017-08-04 11:33:49 -070092 int y = 1970 + static_cast<int>(t / (365.2425 * 86400000.0));
Lei Zhangab5939e2017-06-16 02:23:18 -070093 if (TimeFromYear(y) <= t) {
94 while (TimeFromYear(y + 1) <= t)
95 y++;
96 } else {
97 while (TimeFromYear(y) > t)
98 y--;
99 }
100 return y;
101}
102
103int DayWithinYear(double t) {
104 int year = YearFromTime(t);
105 int day = Day(t);
106 return day - DayFromYear(year);
107}
108
109int MonthFromTime(double t) {
110 int day = DayWithinYear(t);
111 int year = YearFromTime(t);
112 if (0 <= day && day < 31)
113 return 0;
114 if (31 <= day && day < 59 + IsLeapYear(year))
115 return 1;
116 if ((59 + IsLeapYear(year)) <= day && day < (90 + IsLeapYear(year)))
117 return 2;
118 if ((90 + IsLeapYear(year)) <= day && day < (120 + IsLeapYear(year)))
119 return 3;
120 if ((120 + IsLeapYear(year)) <= day && day < (151 + IsLeapYear(year)))
121 return 4;
122 if ((151 + IsLeapYear(year)) <= day && day < (181 + IsLeapYear(year)))
123 return 5;
124 if ((181 + IsLeapYear(year)) <= day && day < (212 + IsLeapYear(year)))
125 return 6;
126 if ((212 + IsLeapYear(year)) <= day && day < (243 + IsLeapYear(year)))
127 return 7;
128 if ((243 + IsLeapYear(year)) <= day && day < (273 + IsLeapYear(year)))
129 return 8;
130 if ((273 + IsLeapYear(year)) <= day && day < (304 + IsLeapYear(year)))
131 return 9;
132 if ((304 + IsLeapYear(year)) <= day && day < (334 + IsLeapYear(year)))
133 return 10;
134 if ((334 + IsLeapYear(year)) <= day && day < (365 + IsLeapYear(year)))
135 return 11;
136
137 return -1;
138}
139
140int DateFromTime(double t) {
141 int day = DayWithinYear(t);
142 int year = YearFromTime(t);
143 int leap = IsLeapYear(year);
144 int month = MonthFromTime(t);
145 switch (month) {
146 case 0:
147 return day + 1;
148 case 1:
149 return day - 30;
150 case 2:
151 return day - 58 - leap;
152 case 3:
153 return day - 89 - leap;
154 case 4:
155 return day - 119 - leap;
156 case 5:
157 return day - 150 - leap;
158 case 6:
159 return day - 180 - leap;
160 case 7:
161 return day - 211 - leap;
162 case 8:
163 return day - 242 - leap;
164 case 9:
165 return day - 272 - leap;
166 case 10:
167 return day - 303 - leap;
168 case 11:
169 return day - 333 - leap;
170 default:
171 return 0;
172 }
173}
174
Dan Sinclairc9708952017-10-23 09:40:59 -0400175double JS_LocalTime(double d) {
176 return d + GetLocalTZA() + GetDaylightSavingTA(d);
177}
178
tsepezfbf52c22016-07-25 11:17:07 -0700179} // namespace
180
Dan Sinclair8f524d62017-10-25 13:30:31 -0400181CJS_Return::CJS_Return(bool result) : is_error_(!result) {}
182
183CJS_Return::CJS_Return(const WideString& err) : is_error_(true), error_(err) {}
184
185CJS_Return::CJS_Return(v8::Local<v8::Value> ret)
186 : is_error_(false), return_(ret) {}
187
188CJS_Return::CJS_Return(const CJS_Return&) = default;
189
190CJS_Return::~CJS_Return() = default;
191
Dan Sinclaire4974922017-10-24 09:36:16 -0400192CJS_Value::CJS_Value() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193
Dan Sinclaire4974922017-10-24 09:36:16 -0400194CJS_Value::CJS_Value(v8::Local<v8::Value> pValue) : m_pValue(pValue) {}
Tom Sepez67fd5df2015-10-08 12:24:19 -0700195
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700196CJS_Value::~CJS_Value() {}
197
weili625ad662016-06-15 11:21:33 -0700198CJS_Value::CJS_Value(const CJS_Value& other) = default;
199
Dan Sinclaire4974922017-10-24 09:36:16 -0400200void CJS_Value::Set(v8::Local<v8::Value> pValue) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700201 m_pValue = pValue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700202}
203
Dan Sinclaire4974922017-10-24 09:36:16 -0400204v8::Local<v8::Value> CJS_Value::ToV8Value() const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700205 return m_pValue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700206}
207
tsepeze5aff742016-08-08 09:49:42 -0700208CJS_Array::CJS_Array() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209
Dan Sinclairc9708952017-10-23 09:40:59 -0400210CJS_Array::CJS_Array(v8::Local<v8::Array> pArray) : m_pArray(pArray) {}
211
weili625ad662016-06-15 11:21:33 -0700212CJS_Array::CJS_Array(const CJS_Array& other) = default;
213
tsepeze5aff742016-08-08 09:49:42 -0700214CJS_Array::~CJS_Array() {}
215
dan sinclair80435cb2017-10-24 21:40:24 -0400216v8::Local<v8::Value> CJS_Array::GetElement(CJS_Runtime* pRuntime,
217 unsigned index) const {
tsepeze5aff742016-08-08 09:49:42 -0700218 if (!m_pArray.IsEmpty())
dan sinclair80435cb2017-10-24 21:40:24 -0400219 return {pRuntime->GetArrayElement(m_pArray, index)};
Dan Sinclaire4974922017-10-24 09:36:16 -0400220 return {};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700221}
222
tsepezb4694242016-08-15 16:44:55 -0700223void CJS_Array::SetElement(CJS_Runtime* pRuntime,
tsepeze5aff742016-08-08 09:49:42 -0700224 unsigned index,
dan sinclair80435cb2017-10-24 21:40:24 -0400225 v8::Local<v8::Value> value) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 if (m_pArray.IsEmpty())
tsepezb4694242016-08-15 16:44:55 -0700227 m_pArray = pRuntime->NewArray();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700228
dan sinclair80435cb2017-10-24 21:40:24 -0400229 pRuntime->PutArrayElement(m_pArray, index, value);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700230}
231
tsepezb4694242016-08-15 16:44:55 -0700232int CJS_Array::GetLength(CJS_Runtime* pRuntime) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700233 if (m_pArray.IsEmpty())
234 return 0;
tsepezb4694242016-08-15 16:44:55 -0700235 return pRuntime->GetArrayLength(m_pArray);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700236}
237
tsepezf3c88322016-08-09 07:30:38 -0700238CJS_Date::CJS_Date() {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700239
Dan Sinclairc9708952017-10-23 09:40:59 -0400240CJS_Date::CJS_Date(v8::Local<v8::Date> pDate) : m_pDate(pDate) {}
241
tsepezb4694242016-08-15 16:44:55 -0700242CJS_Date::CJS_Date(CJS_Runtime* pRuntime, double dMsecTime)
243 : m_pDate(pRuntime->NewDate(dMsecTime)) {}
Tom Sepez67fd5df2015-10-08 12:24:19 -0700244
tsepezb4694242016-08-15 16:44:55 -0700245CJS_Date::CJS_Date(CJS_Runtime* pRuntime,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700246 int year,
247 int mon,
248 int day,
249 int hour,
250 int min,
Tom Sepez67fd5df2015-10-08 12:24:19 -0700251 int sec)
tsepezb4694242016-08-15 16:44:55 -0700252 : m_pDate(pRuntime->NewDate(MakeDate(year, mon, day, hour, min, sec, 0))) {}
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700253
dan sinclaircbe23db2017-10-19 14:29:33 -0400254CJS_Date::CJS_Date(const CJS_Date& other) = default;
255
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700256CJS_Date::~CJS_Date() {}
257
tsepezb4694242016-08-15 16:44:55 -0700258bool CJS_Date::IsValidDate(CJS_Runtime* pRuntime) const {
Tom Sepezdf950b82017-08-04 11:33:49 -0700259 return !m_pDate.IsEmpty() && !std::isnan(pRuntime->ToDouble(m_pDate));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700260}
261
tsepezb4694242016-08-15 16:44:55 -0700262int CJS_Date::GetYear(CJS_Runtime* pRuntime) const {
263 if (!IsValidDate(pRuntime))
tsepezfbf52c22016-07-25 11:17:07 -0700264 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700265
tsepeze6cf0132017-01-18 14:38:18 -0800266 return JS_GetYearFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700267}
268
tsepezb4694242016-08-15 16:44:55 -0700269int CJS_Date::GetMonth(CJS_Runtime* pRuntime) const {
270 if (!IsValidDate(pRuntime))
tsepezfbf52c22016-07-25 11:17:07 -0700271 return 0;
tsepeze6cf0132017-01-18 14:38:18 -0800272 return JS_GetMonthFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700273}
274
tsepezb4694242016-08-15 16:44:55 -0700275int CJS_Date::GetDay(CJS_Runtime* pRuntime) const {
276 if (!IsValidDate(pRuntime))
tsepezfbf52c22016-07-25 11:17:07 -0700277 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700278
tsepeze6cf0132017-01-18 14:38:18 -0800279 return JS_GetDayFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700280}
281
tsepezb4694242016-08-15 16:44:55 -0700282int CJS_Date::GetHours(CJS_Runtime* pRuntime) const {
283 if (!IsValidDate(pRuntime))
tsepezfbf52c22016-07-25 11:17:07 -0700284 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700285
tsepeze6cf0132017-01-18 14:38:18 -0800286 return JS_GetHourFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700287}
288
tsepezb4694242016-08-15 16:44:55 -0700289int CJS_Date::GetMinutes(CJS_Runtime* pRuntime) const {
290 if (!IsValidDate(pRuntime))
tsepezfbf52c22016-07-25 11:17:07 -0700291 return 0;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700292
tsepeze6cf0132017-01-18 14:38:18 -0800293 return JS_GetMinFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700294}
295
tsepezb4694242016-08-15 16:44:55 -0700296int CJS_Date::GetSeconds(CJS_Runtime* pRuntime) const {
297 if (!IsValidDate(pRuntime))
tsepezfbf52c22016-07-25 11:17:07 -0700298 return 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700299
tsepeze6cf0132017-01-18 14:38:18 -0800300 return JS_GetSecFromTime(JS_LocalTime(pRuntime->ToDouble(m_pDate)));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700301}
302
Tom Sepez39bfe122015-09-17 15:25:23 -0700303double JS_GetDateTime() {
304 if (!FSDK_IsSandBoxPolicyEnabled(FPDF_POLICY_MACHINETIME_ACCESS))
305 return 0;
thestig1cd352e2016-06-07 17:53:06 -0700306 time_t t = time(nullptr);
Tom Sepez39bfe122015-09-17 15:25:23 -0700307 struct tm* pTm = localtime(&t);
308
309 int year = pTm->tm_year + 1900;
Lei Zhangab5939e2017-06-16 02:23:18 -0700310 double t1 = TimeFromYear(year);
Tom Sepez39bfe122015-09-17 15:25:23 -0700311
312 return t1 + pTm->tm_yday * 86400000.0 + pTm->tm_hour * 3600000.0 +
313 pTm->tm_min * 60000.0 + pTm->tm_sec * 1000.0;
314}
315
316int JS_GetYearFromTime(double dt) {
Lei Zhangab5939e2017-06-16 02:23:18 -0700317 return YearFromTime(dt);
Tom Sepez39bfe122015-09-17 15:25:23 -0700318}
319
320int JS_GetMonthFromTime(double dt) {
Lei Zhangab5939e2017-06-16 02:23:18 -0700321 return MonthFromTime(dt);
Tom Sepez39bfe122015-09-17 15:25:23 -0700322}
323
324int JS_GetDayFromTime(double dt) {
Lei Zhangab5939e2017-06-16 02:23:18 -0700325 return DateFromTime(dt);
Tom Sepez39bfe122015-09-17 15:25:23 -0700326}
327
328int JS_GetHourFromTime(double dt) {
Lei Zhangab5939e2017-06-16 02:23:18 -0700329 return (int)Mod(floor(dt / (60 * 60 * 1000)), 24);
Tom Sepez39bfe122015-09-17 15:25:23 -0700330}
331
332int JS_GetMinFromTime(double dt) {
Lei Zhangab5939e2017-06-16 02:23:18 -0700333 return (int)Mod(floor(dt / (60 * 1000)), 60);
Tom Sepez39bfe122015-09-17 15:25:23 -0700334}
335
336int JS_GetSecFromTime(double dt) {
Lei Zhangab5939e2017-06-16 02:23:18 -0700337 return (int)Mod(floor(dt / 1000), 60);
Tom Sepez39bfe122015-09-17 15:25:23 -0700338}
339
Ryan Harrison275e2602017-09-18 14:23:18 -0400340double JS_DateParse(const WideString& str) {
Tom Sepez39bfe122015-09-17 15:25:23 -0700341 v8::Isolate* pIsolate = v8::Isolate::GetCurrent();
342 v8::Isolate::Scope isolate_scope(pIsolate);
343 v8::HandleScope scope(pIsolate);
344
345 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
346
347 // Use the built-in object method.
348 v8::Local<v8::Value> v =
349 context->Global()
350 ->Get(context, v8::String::NewFromUtf8(pIsolate, "Date",
351 v8::NewStringType::kNormal)
352 .ToLocalChecked())
353 .ToLocalChecked();
354 if (v->IsObject()) {
355 v8::Local<v8::Object> o = v->ToObject(context).ToLocalChecked();
356 v = o->Get(context, v8::String::NewFromUtf8(pIsolate, "parse",
357 v8::NewStringType::kNormal)
Dan Sinclairf766ad22016-03-14 13:51:24 -0400358 .ToLocalChecked())
359 .ToLocalChecked();
Tom Sepez39bfe122015-09-17 15:25:23 -0700360 if (v->IsFunction()) {
361 v8::Local<v8::Function> funC = v8::Local<v8::Function>::Cast(v);
Tom Sepez39bfe122015-09-17 15:25:23 -0700362 const int argc = 1;
Tom Sepezc6dc69f2017-02-23 09:53:09 -0800363 v8::Local<v8::Value> timeStr =
364 CJS_Runtime::CurrentRuntimeFromIsolate(pIsolate)->NewString(
Ryan Harrison275e2602017-09-18 14:23:18 -0400365 str.AsStringView());
Tom Sepez39bfe122015-09-17 15:25:23 -0700366 v8::Local<v8::Value> argv[argc] = {timeStr};
367 v = funC->Call(context, context->Global(), argc, argv).ToLocalChecked();
368 if (v->IsNumber()) {
369 double date = v->ToNumber(context).ToLocalChecked()->Value();
Tom Sepezdf950b82017-08-04 11:33:49 -0700370 if (!std::isfinite(date))
Tom Sepez39bfe122015-09-17 15:25:23 -0700371 return date;
tsepez86a61dc2016-03-25 10:00:11 -0700372 return JS_LocalTime(date);
Tom Sepez39bfe122015-09-17 15:25:23 -0700373 }
374 }
375 }
376 return 0;
377}
378
379double JS_MakeDay(int nYear, int nMonth, int nDate) {
Tom Sepezdf950b82017-08-04 11:33:49 -0700380 double y = static_cast<double>(nYear);
381 double m = static_cast<double>(nMonth);
382 double dt = static_cast<double>(nDate);
383 double ym = y + floor(m / 12);
Lei Zhangab5939e2017-06-16 02:23:18 -0700384 double mn = Mod(m, 12);
Tom Sepezdf950b82017-08-04 11:33:49 -0700385 double t = TimeFromYearMonth(static_cast<int>(ym), static_cast<int>(mn));
Lei Zhangab5939e2017-06-16 02:23:18 -0700386 if (YearFromTime(t) != ym || MonthFromTime(t) != mn || DateFromTime(t) != 1)
Tom Sepezdf950b82017-08-04 11:33:49 -0700387 return std::nan("");
388
Lei Zhangab5939e2017-06-16 02:23:18 -0700389 return Day(t) + dt - 1;
Tom Sepez39bfe122015-09-17 15:25:23 -0700390}
391
392double JS_MakeTime(int nHour, int nMin, int nSec, int nMs) {
Tom Sepezdf950b82017-08-04 11:33:49 -0700393 double h = static_cast<double>(nHour);
394 double m = static_cast<double>(nMin);
395 double s = static_cast<double>(nSec);
396 double milli = static_cast<double>(nMs);
Tom Sepez39bfe122015-09-17 15:25:23 -0700397 return h * 3600000 + m * 60000 + s * 1000 + milli;
398}
399
400double JS_MakeDate(double day, double time) {
Tom Sepezdf950b82017-08-04 11:33:49 -0700401 if (!std::isfinite(day) || !std::isfinite(time))
402 return std::nan("");
Tom Sepez39bfe122015-09-17 15:25:23 -0700403
404 return day * 86400000 + time;
405}
406
dan sinclair80435cb2017-10-24 21:40:24 -0400407std::vector<v8::Local<v8::Value>> ExpandKeywordParams(
Tom Sepezbd932572016-01-29 09:10:41 -0800408 CJS_Runtime* pRuntime,
dan sinclair80435cb2017-10-24 21:40:24 -0400409 const std::vector<v8::Local<v8::Value>>& originals,
Tom Sepezbd932572016-01-29 09:10:41 -0800410 size_t nKeywords,
411 ...) {
412 ASSERT(nKeywords);
413
dan sinclair80435cb2017-10-24 21:40:24 -0400414 std::vector<v8::Local<v8::Value>> result(nKeywords, v8::Local<v8::Value>());
Tom Sepezbd932572016-01-29 09:10:41 -0800415 size_t size = std::min(originals.size(), nKeywords);
416 for (size_t i = 0; i < size; ++i)
417 result[i] = originals[i];
418
dan sinclair80435cb2017-10-24 21:40:24 -0400419 if (originals.size() != 1 || !originals[0]->IsObject() ||
420 originals[0]->IsArray()) {
Tom Sepezbd932572016-01-29 09:10:41 -0800421 return result;
422 }
dan sinclair80435cb2017-10-24 21:40:24 -0400423 result[0] = v8::Local<v8::Value>(); // Make unknown.
Tom Sepezbd932572016-01-29 09:10:41 -0800424
dan sinclair80435cb2017-10-24 21:40:24 -0400425 v8::Local<v8::Object> pObj = pRuntime->ToObject(originals[0]);
Tom Sepezbd932572016-01-29 09:10:41 -0800426 va_list ap;
427 va_start(ap, nKeywords);
Wei Li89409932016-03-28 10:33:33 -0700428 for (size_t i = 0; i < nKeywords; ++i) {
Tom Sepezbd932572016-01-29 09:10:41 -0800429 const wchar_t* property = va_arg(ap, const wchar_t*);
tsepezb4694242016-08-15 16:44:55 -0700430 v8::Local<v8::Value> v8Value = pRuntime->GetObjectProperty(pObj, property);
Tom Sepezbd932572016-01-29 09:10:41 -0800431 if (!v8Value->IsUndefined())
dan sinclair80435cb2017-10-24 21:40:24 -0400432 result[i] = v8Value;
Tom Sepezbd932572016-01-29 09:10:41 -0800433 }
434 va_end(ap);
dan sinclair80435cb2017-10-24 21:40:24 -0400435
Tom Sepezbd932572016-01-29 09:10:41 -0800436 return result;
437}