blob: bbf1ec64f0a0974822b98d3d506316fde477edd1 [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2020 The PDFium Authors
Tom Sepez3466e272020-03-18 23:33:35 +00002// 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
Tom Sepezd5a7e7f2021-11-10 03:05:00 +00009#include "third_party/base/numerics/safe_conversions.h"
Dan Elphick05673a32021-09-09 15:42:55 +000010#include "v8/include/v8-container.h"
11#include "v8/include/v8-date.h"
12#include "v8/include/v8-exception.h"
13#include "v8/include/v8-isolate.h"
14#include "v8/include/v8-primitive.h"
15#include "v8/include/v8-value.h"
16
Tom Sepez3466e272020-03-18 23:33:35 +000017namespace fxv8 {
18
Tom Sepezaf6371f2020-11-02 20:13:01 +000019bool IsUndefined(v8::Local<v8::Value> value) {
20 return !value.IsEmpty() && value->IsUndefined();
21}
22
23bool IsNull(v8::Local<v8::Value> value) {
24 return !value.IsEmpty() && value->IsNull();
25}
26
27bool IsBoolean(v8::Local<v8::Value> value) {
28 return !value.IsEmpty() && value->IsBoolean();
29}
30
31bool IsString(v8::Local<v8::Value> value) {
32 return !value.IsEmpty() && value->IsString();
33}
34
35bool IsNumber(v8::Local<v8::Value> value) {
36 return !value.IsEmpty() && value->IsNumber();
37}
38
39bool IsInteger(v8::Local<v8::Value> value) {
40 return !value.IsEmpty() && value->IsInt32();
41}
42
43bool IsObject(v8::Local<v8::Value> value) {
44 return !value.IsEmpty() && value->IsObject();
45}
46
47bool IsArray(v8::Local<v8::Value> value) {
48 return !value.IsEmpty() && value->IsArray();
49}
50
51bool IsDate(v8::Local<v8::Value> value) {
52 return !value.IsEmpty() && value->IsDate();
53}
54
55bool IsFunction(v8::Local<v8::Value> value) {
56 return !value.IsEmpty() && value->IsFunction();
57}
58
Tom Sepez1512c362020-03-19 22:13:52 +000059v8::Local<v8::Value> NewNullHelper(v8::Isolate* pIsolate) {
60 return v8::Null(pIsolate);
61}
62
63v8::Local<v8::Value> NewUndefinedHelper(v8::Isolate* pIsolate) {
64 return v8::Undefined(pIsolate);
65}
66
67v8::Local<v8::Number> NewNumberHelper(v8::Isolate* pIsolate, int number) {
68 return v8::Int32::New(pIsolate, number);
69}
70
71v8::Local<v8::Number> NewNumberHelper(v8::Isolate* pIsolate, double number) {
72 return v8::Number::New(pIsolate, number);
73}
74
75v8::Local<v8::Number> NewNumberHelper(v8::Isolate* pIsolate, float number) {
76 return v8::Number::New(pIsolate, number);
77}
78
79v8::Local<v8::Boolean> NewBooleanHelper(v8::Isolate* pIsolate, bool b) {
80 return v8::Boolean::New(pIsolate, b);
81}
82
Tom Sepez3466e272020-03-18 23:33:35 +000083v8::Local<v8::String> NewStringHelper(v8::Isolate* pIsolate,
84 ByteStringView str) {
Tom Sepeza0de6da2021-11-11 01:40:23 +000085 return v8::String::NewFromUtf8(
86 pIsolate, str.unterminated_c_str(), v8::NewStringType::kNormal,
87 pdfium::base::checked_cast<int>(str.GetLength()))
Tom Sepez3466e272020-03-18 23:33:35 +000088 .ToLocalChecked();
89}
90
91v8::Local<v8::String> NewStringHelper(v8::Isolate* pIsolate,
92 WideStringView str) {
93 return NewStringHelper(pIsolate, FX_UTF8Encode(str).AsStringView());
94}
95
Tom Sepez1512c362020-03-19 22:13:52 +000096v8::Local<v8::Array> NewArrayHelper(v8::Isolate* pIsolate) {
97 return v8::Array::New(pIsolate);
98}
99
Tom Sepez145e22d2020-11-18 00:49:06 +0000100v8::Local<v8::Array> NewArrayHelper(v8::Isolate* pIsolate,
101 pdfium::span<v8::Local<v8::Value>> values) {
102 v8::Local<v8::Array> result = NewArrayHelper(pIsolate);
103 for (size_t i = 0; i < values.size(); ++i) {
104 fxv8::ReentrantPutArrayElementHelper(
105 pIsolate, result, i,
106 values[i].IsEmpty() ? fxv8::NewUndefinedHelper(pIsolate) : values[i]);
107 }
108 return result;
109}
110
Tom Sepez1512c362020-03-19 22:13:52 +0000111v8::Local<v8::Object> NewObjectHelper(v8::Isolate* pIsolate) {
112 return v8::Object::New(pIsolate);
113}
114
115v8::Local<v8::Date> NewDateHelper(v8::Isolate* pIsolate, double d) {
116 return v8::Date::New(pIsolate->GetCurrentContext(), d)
117 .ToLocalChecked()
118 .As<v8::Date>();
119}
120
Tom Sepez494efc72020-11-30 20:50:59 +0000121WideString ToWideString(v8::Isolate* pIsolate, v8::Local<v8::String> pValue) {
122 v8::String::Utf8Value s(pIsolate, pValue);
123 return WideString::FromUTF8(ByteStringView(*s, s.length()));
124}
125
126ByteString ToByteString(v8::Isolate* pIsolate, v8::Local<v8::String> pValue) {
127 v8::String::Utf8Value s(pIsolate, pValue);
128 return ByteString(*s, s.length());
129}
130
Tom Sepez3466e272020-03-18 23:33:35 +0000131int ReentrantToInt32Helper(v8::Isolate* pIsolate, v8::Local<v8::Value> pValue) {
132 if (pValue.IsEmpty())
133 return 0;
Tom Sepez5f3e5812020-08-11 22:46:10 +0000134 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez3466e272020-03-18 23:33:35 +0000135 return pValue->Int32Value(pIsolate->GetCurrentContext()).FromMaybe(0);
136}
137
138bool ReentrantToBooleanHelper(v8::Isolate* pIsolate,
139 v8::Local<v8::Value> pValue) {
140 if (pValue.IsEmpty())
141 return false;
Tom Sepez5f3e5812020-08-11 22:46:10 +0000142 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez3466e272020-03-18 23:33:35 +0000143 return pValue->BooleanValue(pIsolate);
144}
145
Tom Sepezd564b0d2020-11-06 18:28:10 +0000146float ReentrantToFloatHelper(v8::Isolate* pIsolate,
147 v8::Local<v8::Value> pValue) {
148 return static_cast<float>(ReentrantToDoubleHelper(pIsolate, pValue));
149}
150
Tom Sepez3466e272020-03-18 23:33:35 +0000151double ReentrantToDoubleHelper(v8::Isolate* pIsolate,
152 v8::Local<v8::Value> pValue) {
153 if (pValue.IsEmpty())
154 return 0.0;
Tom Sepez5f3e5812020-08-11 22:46:10 +0000155 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez3466e272020-03-18 23:33:35 +0000156 return pValue->NumberValue(pIsolate->GetCurrentContext()).FromMaybe(0.0);
157}
158
159WideString ReentrantToWideStringHelper(v8::Isolate* pIsolate,
160 v8::Local<v8::Value> pValue) {
161 if (pValue.IsEmpty())
162 return WideString();
Tom Sepezc72e23f2020-03-19 18:58:17 +0000163
Tom Sepez5f3e5812020-08-11 22:46:10 +0000164 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez3466e272020-03-18 23:33:35 +0000165 v8::MaybeLocal<v8::String> maybe_string =
166 pValue->ToString(pIsolate->GetCurrentContext());
167 if (maybe_string.IsEmpty())
168 return WideString();
Tom Sepezc72e23f2020-03-19 18:58:17 +0000169
Tom Sepez494efc72020-11-30 20:50:59 +0000170 return ToWideString(pIsolate, maybe_string.ToLocalChecked());
Tom Sepez3466e272020-03-18 23:33:35 +0000171}
172
173ByteString ReentrantToByteStringHelper(v8::Isolate* pIsolate,
174 v8::Local<v8::Value> pValue) {
175 if (pValue.IsEmpty())
176 return ByteString();
Tom Sepezc72e23f2020-03-19 18:58:17 +0000177
Tom Sepez5f3e5812020-08-11 22:46:10 +0000178 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez3466e272020-03-18 23:33:35 +0000179 v8::MaybeLocal<v8::String> maybe_string =
180 pValue->ToString(pIsolate->GetCurrentContext());
181 if (maybe_string.IsEmpty())
182 return ByteString();
Tom Sepezc72e23f2020-03-19 18:58:17 +0000183
Tom Sepez494efc72020-11-30 20:50:59 +0000184 return ToByteString(pIsolate, maybe_string.ToLocalChecked());
Tom Sepez3466e272020-03-18 23:33:35 +0000185}
186
Tom Sepez1512c362020-03-19 22:13:52 +0000187v8::Local<v8::Object> ReentrantToObjectHelper(v8::Isolate* pIsolate,
188 v8::Local<v8::Value> pValue) {
Tom Sepezaf6371f2020-11-02 20:13:01 +0000189 if (!fxv8::IsObject(pValue))
Tom Sepez1512c362020-03-19 22:13:52 +0000190 return v8::Local<v8::Object>();
Tom Sepez5f3e5812020-08-11 22:46:10 +0000191
192 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez1512c362020-03-19 22:13:52 +0000193 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
194 return pValue->ToObject(context).ToLocalChecked();
195}
196
197v8::Local<v8::Array> ReentrantToArrayHelper(v8::Isolate* pIsolate,
198 v8::Local<v8::Value> pValue) {
Tom Sepezaf6371f2020-11-02 20:13:01 +0000199 if (!fxv8::IsArray(pValue))
Tom Sepez1512c362020-03-19 22:13:52 +0000200 return v8::Local<v8::Array>();
Tom Sepez5f3e5812020-08-11 22:46:10 +0000201
202 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez1512c362020-03-19 22:13:52 +0000203 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
204 return v8::Local<v8::Array>::Cast(pValue->ToObject(context).ToLocalChecked());
205}
206
Tom Sepezc72e23f2020-03-19 18:58:17 +0000207v8::Local<v8::Value> ReentrantGetObjectPropertyHelper(
208 v8::Isolate* pIsolate,
209 v8::Local<v8::Object> pObj,
210 ByteStringView bsUTF8PropertyName) {
211 if (pObj.IsEmpty())
212 return v8::Local<v8::Value>();
213
Tom Sepez5f3e5812020-08-11 22:46:10 +0000214 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepezc72e23f2020-03-19 18:58:17 +0000215 v8::Local<v8::Value> val;
216 if (!pObj->Get(pIsolate->GetCurrentContext(),
217 NewStringHelper(pIsolate, bsUTF8PropertyName))
218 .ToLocal(&val)) {
219 return v8::Local<v8::Value>();
220 }
221 return val;
222}
223
224std::vector<WideString> ReentrantGetObjectPropertyNamesHelper(
225 v8::Isolate* pIsolate,
226 v8::Local<v8::Object> pObj) {
227 if (pObj.IsEmpty())
228 return std::vector<WideString>();
229
Tom Sepez5f3e5812020-08-11 22:46:10 +0000230 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepezc72e23f2020-03-19 18:58:17 +0000231 v8::Local<v8::Array> val;
232 v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
233 if (!pObj->GetPropertyNames(context).ToLocal(&val))
234 return std::vector<WideString>();
235
236 std::vector<WideString> result;
237 for (uint32_t i = 0; i < val->Length(); ++i) {
238 result.push_back(ReentrantToWideStringHelper(
239 pIsolate, val->Get(context, i).ToLocalChecked()));
240 }
241 return result;
242}
243
Tom Sepezf4874452020-11-09 21:14:06 +0000244bool ReentrantHasObjectOwnPropertyHelper(v8::Isolate* pIsolate,
245 v8::Local<v8::Object> pObj,
Tom Sepez47793dc2021-05-26 20:03:38 +0000246 ByteStringView bsUTF8PropertyName) {
Tom Sepezf4874452020-11-09 21:14:06 +0000247 if (pObj.IsEmpty())
248 return false;
249
250 v8::TryCatch squash_exceptions(pIsolate);
251 v8::Local<v8::Context> pContext = pIsolate->GetCurrentContext();
252 v8::Local<v8::String> hKey =
253 fxv8::NewStringHelper(pIsolate, bsUTF8PropertyName);
Tom Sepez47793dc2021-05-26 20:03:38 +0000254 return pObj->HasRealNamedProperty(pContext, hKey).FromJust();
Tom Sepezf4874452020-11-09 21:14:06 +0000255}
256
257bool ReentrantSetObjectOwnPropertyHelper(v8::Isolate* pIsolate,
258 v8::Local<v8::Object> pObj,
259 ByteStringView bsUTF8PropertyName,
260 v8::Local<v8::Value> pValue) {
Tom Sepezab436ae2020-11-20 19:57:20 +0000261 if (pObj.IsEmpty() || pValue.IsEmpty())
Tom Sepezf4874452020-11-09 21:14:06 +0000262 return false;
263
264 v8::TryCatch squash_exceptions(pIsolate);
265 v8::Local<v8::String> name = NewStringHelper(pIsolate, bsUTF8PropertyName);
266 return pObj->DefineOwnProperty(pIsolate->GetCurrentContext(), name, pValue)
267 .FromMaybe(false);
268}
269
Tom Sepezc72e23f2020-03-19 18:58:17 +0000270bool ReentrantPutObjectPropertyHelper(v8::Isolate* pIsolate,
271 v8::Local<v8::Object> pObj,
272 ByteStringView bsUTF8PropertyName,
273 v8::Local<v8::Value> pPut) {
Tom Sepezab436ae2020-11-20 19:57:20 +0000274 if (pObj.IsEmpty() || pPut.IsEmpty())
Tom Sepezc72e23f2020-03-19 18:58:17 +0000275 return false;
276
Tom Sepez5f3e5812020-08-11 22:46:10 +0000277 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepezc72e23f2020-03-19 18:58:17 +0000278 v8::Local<v8::String> name = NewStringHelper(pIsolate, bsUTF8PropertyName);
Tom Sepez2fb992d2020-03-20 19:45:59 +0000279 v8::Maybe<bool> result = pObj->Set(pIsolate->GetCurrentContext(), name, pPut);
280 return result.IsJust() && result.FromJust();
Tom Sepezc72e23f2020-03-19 18:58:17 +0000281}
282
Tom Sepez4643cf62020-11-09 19:27:05 +0000283void ReentrantDeleteObjectPropertyHelper(v8::Isolate* pIsolate,
284 v8::Local<v8::Object> pObj,
285 ByteStringView bsUTF8PropertyName) {
286 v8::TryCatch squash_exceptions(pIsolate);
287 pObj->Delete(pIsolate->GetCurrentContext(),
288 fxv8::NewStringHelper(pIsolate, bsUTF8PropertyName))
289 .FromJust();
290}
291
Tom Sepez1512c362020-03-19 22:13:52 +0000292bool ReentrantPutArrayElementHelper(v8::Isolate* pIsolate,
293 v8::Local<v8::Array> pArray,
Tom Sepezd5a7e7f2021-11-10 03:05:00 +0000294 size_t index,
Tom Sepez1512c362020-03-19 22:13:52 +0000295 v8::Local<v8::Value> pValue) {
296 if (pArray.IsEmpty())
297 return false;
Tom Sepez2fb992d2020-03-20 19:45:59 +0000298
Tom Sepez5f3e5812020-08-11 22:46:10 +0000299 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez2fb992d2020-03-20 19:45:59 +0000300 v8::Maybe<bool> result =
Tom Sepezd5a7e7f2021-11-10 03:05:00 +0000301 pArray->Set(pIsolate->GetCurrentContext(),
302 pdfium::base::checked_cast<uint32_t>(index), pValue);
Tom Sepez2fb992d2020-03-20 19:45:59 +0000303 return result.IsJust() && result.FromJust();
Tom Sepez1512c362020-03-19 22:13:52 +0000304}
305
306v8::Local<v8::Value> ReentrantGetArrayElementHelper(v8::Isolate* pIsolate,
307 v8::Local<v8::Array> pArray,
Tom Sepezd5a7e7f2021-11-10 03:05:00 +0000308 size_t index) {
Tom Sepez1512c362020-03-19 22:13:52 +0000309 if (pArray.IsEmpty())
310 return v8::Local<v8::Value>();
Tom Sepez5f3e5812020-08-11 22:46:10 +0000311
312 v8::TryCatch squash_exceptions(pIsolate);
Tom Sepez1512c362020-03-19 22:13:52 +0000313 v8::Local<v8::Value> val;
Tom Sepezd5a7e7f2021-11-10 03:05:00 +0000314 if (!pArray
315 ->Get(pIsolate->GetCurrentContext(),
316 pdfium::base::checked_cast<uint32_t>(index))
317 .ToLocal(&val)) {
Tom Sepez1512c362020-03-19 22:13:52 +0000318 return v8::Local<v8::Value>();
Tom Sepezd5a7e7f2021-11-10 03:05:00 +0000319 }
Tom Sepez1512c362020-03-19 22:13:52 +0000320 return val;
321}
322
Tom Sepezd5a7e7f2021-11-10 03:05:00 +0000323size_t GetArrayLengthHelper(v8::Local<v8::Array> pArray) {
Tom Sepez1512c362020-03-19 22:13:52 +0000324 if (pArray.IsEmpty())
325 return 0;
326 return pArray->Length();
327}
328
Tom Sepezacc07782020-03-19 20:02:00 +0000329void ThrowExceptionHelper(v8::Isolate* pIsolate, ByteStringView str) {
330 pIsolate->ThrowException(NewStringHelper(pIsolate, str));
331}
332
333void ThrowExceptionHelper(v8::Isolate* pIsolate, WideStringView str) {
334 pIsolate->ThrowException(NewStringHelper(pIsolate, str));
335}
336
Tom Sepez3466e272020-03-18 23:33:35 +0000337} // namespace fxv8