1 // Copyright 2020 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 "fxjs/fxv8.h"
8
9 namespace fxv8 {
10
IsUndefined(v8::Local<v8::Value> value)11 bool IsUndefined(v8::Local<v8::Value> value) {
12 return !value.IsEmpty() && value->IsUndefined();
13 }
14
IsNull(v8::Local<v8::Value> value)15 bool IsNull(v8::Local<v8::Value> value) {
16 return !value.IsEmpty() && value->IsNull();
17 }
18
IsBoolean(v8::Local<v8::Value> value)19 bool IsBoolean(v8::Local<v8::Value> value) {
20 return !value.IsEmpty() && value->IsBoolean();
21 }
22
IsString(v8::Local<v8::Value> value)23 bool IsString(v8::Local<v8::Value> value) {
24 return !value.IsEmpty() && value->IsString();
25 }
26
IsNumber(v8::Local<v8::Value> value)27 bool IsNumber(v8::Local<v8::Value> value) {
28 return !value.IsEmpty() && value->IsNumber();
29 }
30
IsInteger(v8::Local<v8::Value> value)31 bool IsInteger(v8::Local<v8::Value> value) {
32 return !value.IsEmpty() && value->IsInt32();
33 }
34
IsObject(v8::Local<v8::Value> value)35 bool IsObject(v8::Local<v8::Value> value) {
36 return !value.IsEmpty() && value->IsObject();
37 }
38
IsArray(v8::Local<v8::Value> value)39 bool IsArray(v8::Local<v8::Value> value) {
40 return !value.IsEmpty() && value->IsArray();
41 }
42
IsDate(v8::Local<v8::Value> value)43 bool IsDate(v8::Local<v8::Value> value) {
44 return !value.IsEmpty() && value->IsDate();
45 }
46
IsFunction(v8::Local<v8::Value> value)47 bool IsFunction(v8::Local<v8::Value> value) {
48 return !value.IsEmpty() && value->IsFunction();
49 }
50
NewNullHelper(v8::Isolate * pIsolate)51 v8::Local<v8::Value> NewNullHelper(v8::Isolate* pIsolate) {
52 return v8::Null(pIsolate);
53 }
54
NewUndefinedHelper(v8::Isolate * pIsolate)55 v8::Local<v8::Value> NewUndefinedHelper(v8::Isolate* pIsolate) {
56 return v8::Undefined(pIsolate);
57 }
58
NewNumberHelper(v8::Isolate * pIsolate,int number)59 v8::Local<v8::Number> NewNumberHelper(v8::Isolate* pIsolate, int number) {
60 return v8::Int32::New(pIsolate, number);
61 }
62
NewNumberHelper(v8::Isolate * pIsolate,double number)63 v8::Local<v8::Number> NewNumberHelper(v8::Isolate* pIsolate, double number) {
64 return v8::Number::New(pIsolate, number);
65 }
66
NewNumberHelper(v8::Isolate * pIsolate,float number)67 v8::Local<v8::Number> NewNumberHelper(v8::Isolate* pIsolate, float number) {
68 return v8::Number::New(pIsolate, number);
69 }
70
NewBooleanHelper(v8::Isolate * pIsolate,bool b)71 v8::Local<v8::Boolean> NewBooleanHelper(v8::Isolate* pIsolate, bool b) {
72 return v8::Boolean::New(pIsolate, b);
73 }
74
NewStringHelper(v8::Isolate * pIsolate,ByteStringView str)75 v8::Local<v8::String> NewStringHelper(v8::Isolate* pIsolate,
76 ByteStringView str) {
77 return v8::String::NewFromUtf8(pIsolate, str.unterminated_c_str(),
78 v8::NewStringType::kNormal, str.GetLength())
79 .ToLocalChecked();
80 }
81
NewStringHelper(v8::Isolate * pIsolate,WideStringView str)82 v8::Local<v8::String> NewStringHelper(v8::Isolate* pIsolate,
83 WideStringView str) {
84 return NewStringHelper(pIsolate, FX_UTF8Encode(str).AsStringView());
85 }
86
NewArrayHelper(v8::Isolate * pIsolate)87 v8::Local<v8::Array> NewArrayHelper(v8::Isolate* pIsolate) {
88 return v8::Array::New(pIsolate);
89 }
90
NewObjectHelper(v8::Isolate * pIsolate)91 v8::Local<v8::Object> NewObjectHelper(v8::Isolate* pIsolate) {
92 return v8::Object::New(pIsolate);
93 }
94
NewDateHelper(v8::Isolate * pIsolate,double d)95 v8::Local<v8::Date> NewDateHelper(v8::Isolate* pIsolate, double d) {
96 return v8::Date::New(pIsolate->GetCurrentContext(), d)
97 .ToLocalChecked()
98 .As<v8::Date>();
99 }
100
ReentrantToInt32Helper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)101 int ReentrantToInt32Helper(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
102 if (pValue.IsEmpty())
103 return 0;
104 v8::TryCatch squash_exceptions(pIsolate);
105 return pValue->Int32Value(pIsolate->GetCurrentContext()).FromMaybe(0);
106 }
107
ReentrantToBooleanHelper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)108 bool ReentrantToBooleanHelper(v8::Isolate* pIsolate,
109 v8::Local<v8::Value> pValue) {
110 if (pValue.IsEmpty())
111 return false;
112 v8::TryCatch squash_exceptions(pIsolate);
113 return pValue->BooleanValue(pIsolate);
114 }
115
ReentrantToFloatHelper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)116 float ReentrantToFloatHelper(v8::Isolate* pIsolate,
117 v8::Local<v8::Value> pValue) {
118 return static_cast<float>(ReentrantToDoubleHelper(pIsolate, pValue));
119 }
120
ReentrantToDoubleHelper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)121 double ReentrantToDoubleHelper(v8::Isolate* pIsolate,
122 v8::Local<v8::Value> pValue) {
123 if (pValue.IsEmpty())
124 return 0.0;
125 v8::TryCatch squash_exceptions(pIsolate);
126 return pValue->NumberValue(pIsolate->GetCurrentContext()).FromMaybe(0.0);
127 }
128
ReentrantToWideStringHelper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)129 WideString ReentrantToWideStringHelper(v8::Isolate* pIsolate,
130 v8::Local<v8::Value> pValue) {
131 if (pValue.IsEmpty())
132 return WideString();
133
134 v8::TryCatch squash_exceptions(pIsolate);
135 v8::MaybeLocal<v8::String> maybe_string =
136 pValue->ToString(pIsolate->GetCurrentContext());
137 if (maybe_string.IsEmpty())
138 return WideString();
139
140 v8::String::Utf8Value s(pIsolate, maybe_string.ToLocalChecked());
141 return WideString::FromUTF8(ByteStringView(*s, s.length()));
142 }
143
ReentrantToByteStringHelper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)144 ByteString ReentrantToByteStringHelper(v8::Isolate* pIsolate,
145 v8::Local<v8::Value> pValue) {
146 if (pValue.IsEmpty())
147 return ByteString();
148
149 v8::TryCatch squash_exceptions(pIsolate);
150 v8::MaybeLocal<v8::String> maybe_string =
151 pValue->ToString(pIsolate->GetCurrentContext());
152 if (maybe_string.IsEmpty())
153 return ByteString();
154
155 v8::String::Utf8Value s(pIsolate, maybe_string.ToLocalChecked());
156 return ByteString(*s);
157 }
158
ReentrantToObjectHelper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)159 v8::Local<v8::Object> ReentrantToObjectHelper(v8::Isolate* pIsolate,
160 v8::Local<v8::Value> pValue) {
161 if (!fxv8::IsObject(pValue))
162 return v8::Local<v8::Object>();
163
164 v8::TryCatch squash_exceptions(pIsolate);
165 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
166 return pValue->ToObject(context).ToLocalChecked();
167 }
168
ReentrantToArrayHelper(v8::Isolate * pIsolate,v8::Local<v8::Value> pValue)169 v8::Local<v8::Array> ReentrantToArrayHelper(v8::Isolate* pIsolate,
170 v8::Local<v8::Value> pValue) {
171 if (!fxv8::IsArray(pValue))
172 return v8::Local<v8::Array>();
173
174 v8::TryCatch squash_exceptions(pIsolate);
175 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
176 return v8::Local<v8::Array>::Cast(pValue->ToObject(context).ToLocalChecked());
177 }
178
ReentrantGetObjectPropertyHelper(v8::Isolate * pIsolate,v8::Local<v8::Object> pObj,ByteStringView bsUTF8PropertyName)179 v8::Local<v8::Value> ReentrantGetObjectPropertyHelper(
180 v8::Isolate* pIsolate,
181 v8::Local<v8::Object> pObj,
182 ByteStringView bsUTF8PropertyName) {
183 if (pObj.IsEmpty())
184 return v8::Local<v8::Value>();
185
186 v8::TryCatch squash_exceptions(pIsolate);
187 v8::Local<v8::Value> val;
188 if (!pObj->Get(pIsolate->GetCurrentContext(),
189 NewStringHelper(pIsolate, bsUTF8PropertyName))
190 .ToLocal(&val)) {
191 return v8::Local<v8::Value>();
192 }
193 return val;
194 }
195
ReentrantGetObjectPropertyNamesHelper(v8::Isolate * pIsolate,v8::Local<v8::Object> pObj)196 std::vector<WideString> ReentrantGetObjectPropertyNamesHelper(
197 v8::Isolate* pIsolate,
198 v8::Local<v8::Object> pObj) {
199 if (pObj.IsEmpty())
200 return std::vector<WideString>();
201
202 v8::TryCatch squash_exceptions(pIsolate);
203 v8::Local<v8::Array> val;
204 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
205 if (!pObj->GetPropertyNames(context).ToLocal(&val))
206 return std::vector<WideString>();
207
208 std::vector<WideString> result;
209 for (uint32_t i = 0; i < val->Length(); ++i) {
210 result.push_back(ReentrantToWideStringHelper(
211 pIsolate, val->Get(context, i).ToLocalChecked()));
212 }
213 return result;
214 }
215
ReentrantHasObjectOwnPropertyHelper(v8::Isolate * pIsolate,v8::Local<v8::Object> pObj,ByteStringView bsUTF8PropertyName,bool bUseTypeGetter)216 bool ReentrantHasObjectOwnPropertyHelper(v8::Isolate* pIsolate,
217 v8::Local<v8::Object> pObj,
218 ByteStringView bsUTF8PropertyName,
219 bool bUseTypeGetter) {
220 if (pObj.IsEmpty())
221 return false;
222
223 v8::TryCatch squash_exceptions(pIsolate);
224 v8::Local<v8::Context> pContext = pIsolate->GetCurrentContext();
225 v8::Local<v8::String> hKey =
226 fxv8::NewStringHelper(pIsolate, bsUTF8PropertyName);
227 return pObj->HasRealNamedProperty(pContext, hKey).FromJust() ||
228 (bUseTypeGetter &&
229 pObj->HasOwnProperty(pContext, hKey).FromMaybe(false));
230 }
231
ReentrantSetObjectOwnPropertyHelper(v8::Isolate * pIsolate,v8::Local<v8::Object> pObj,ByteStringView bsUTF8PropertyName,v8::Local<v8::Value> pValue)232 bool ReentrantSetObjectOwnPropertyHelper(v8::Isolate* pIsolate,
233 v8::Local<v8::Object> pObj,
234 ByteStringView bsUTF8PropertyName,
235 v8::Local<v8::Value> pValue) {
236 ASSERT(!pValue.IsEmpty());
237 if (pObj.IsEmpty())
238 return false;
239
240 v8::TryCatch squash_exceptions(pIsolate);
241 v8::Local<v8::String> name = NewStringHelper(pIsolate, bsUTF8PropertyName);
242 return pObj->DefineOwnProperty(pIsolate->GetCurrentContext(), name, pValue)
243 .FromMaybe(false);
244 }
245
ReentrantPutObjectPropertyHelper(v8::Isolate * pIsolate,v8::Local<v8::Object> pObj,ByteStringView bsUTF8PropertyName,v8::Local<v8::Value> pPut)246 bool ReentrantPutObjectPropertyHelper(v8::Isolate* pIsolate,
247 v8::Local<v8::Object> pObj,
248 ByteStringView bsUTF8PropertyName,
249 v8::Local<v8::Value> pPut) {
250 ASSERT(!pPut.IsEmpty());
251 if (pObj.IsEmpty())
252 return false;
253
254 v8::TryCatch squash_exceptions(pIsolate);
255 v8::Local<v8::String> name = NewStringHelper(pIsolate, bsUTF8PropertyName);
256 v8::Maybe<bool> result = pObj->Set(pIsolate->GetCurrentContext(), name, pPut);
257 return result.IsJust() && result.FromJust();
258 }
259
ReentrantDeleteObjectPropertyHelper(v8::Isolate * pIsolate,v8::Local<v8::Object> pObj,ByteStringView bsUTF8PropertyName)260 void ReentrantDeleteObjectPropertyHelper(v8::Isolate* pIsolate,
261 v8::Local<v8::Object> pObj,
262 ByteStringView bsUTF8PropertyName) {
263 v8::TryCatch squash_exceptions(pIsolate);
264 pObj->Delete(pIsolate->GetCurrentContext(),
265 fxv8::NewStringHelper(pIsolate, bsUTF8PropertyName))
266 .FromJust();
267 }
268
ReentrantPutArrayElementHelper(v8::Isolate * pIsolate,v8::Local<v8::Array> pArray,unsigned index,v8::Local<v8::Value> pValue)269 bool ReentrantPutArrayElementHelper(v8::Isolate* pIsolate,
270 v8::Local<v8::Array> pArray,
271 unsigned index,
272 v8::Local<v8::Value> pValue) {
273 if (pArray.IsEmpty())
274 return false;
275
276 v8::TryCatch squash_exceptions(pIsolate);
277 v8::Maybe<bool> result =
278 pArray->Set(pIsolate->GetCurrentContext(), index, pValue);
279 return result.IsJust() && result.FromJust();
280 }
281
ReentrantGetArrayElementHelper(v8::Isolate * pIsolate,v8::Local<v8::Array> pArray,unsigned index)282 v8::Local<v8::Value> ReentrantGetArrayElementHelper(v8::Isolate* pIsolate,
283 v8::Local<v8::Array> pArray,
284 unsigned index) {
285 if (pArray.IsEmpty())
286 return v8::Local<v8::Value>();
287
288 v8::TryCatch squash_exceptions(pIsolate);
289 v8::Local<v8::Value> val;
290 if (!pArray->Get(pIsolate->GetCurrentContext(), index).ToLocal(&val))
291 return v8::Local<v8::Value>();
292 return val;
293 }
294
GetArrayLengthHelper(v8::Local<v8::Array> pArray)295 unsigned GetArrayLengthHelper(v8::Local<v8::Array> pArray) {
296 if (pArray.IsEmpty())
297 return 0;
298 return pArray->Length();
299 }
300
ThrowExceptionHelper(v8::Isolate * pIsolate,ByteStringView str)301 void ThrowExceptionHelper(v8::Isolate* pIsolate, ByteStringView str) {
302 pIsolate->ThrowException(NewStringHelper(pIsolate, str));
303 }
304
ThrowExceptionHelper(v8::Isolate * pIsolate,WideStringView str)305 void ThrowExceptionHelper(v8::Isolate* pIsolate, WideStringView str) {
306 pIsolate->ThrowException(NewStringHelper(pIsolate, str));
307 }
308
309 } // namespace fxv8
310