// Copyright 2020 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "fxjs/fxv8.h" #include "third_party/base/numerics/safe_conversions.h" #include "v8/include/v8-container.h" #include "v8/include/v8-date.h" #include "v8/include/v8-exception.h" #include "v8/include/v8-isolate.h" #include "v8/include/v8-primitive.h" #include "v8/include/v8-value.h" namespace fxv8 { bool IsUndefined(v8::Local value) { return !value.IsEmpty() && value->IsUndefined(); } bool IsNull(v8::Local value) { return !value.IsEmpty() && value->IsNull(); } bool IsBoolean(v8::Local value) { return !value.IsEmpty() && value->IsBoolean(); } bool IsString(v8::Local value) { return !value.IsEmpty() && value->IsString(); } bool IsNumber(v8::Local value) { return !value.IsEmpty() && value->IsNumber(); } bool IsInteger(v8::Local value) { return !value.IsEmpty() && value->IsInt32(); } bool IsObject(v8::Local value) { return !value.IsEmpty() && value->IsObject(); } bool IsArray(v8::Local value) { return !value.IsEmpty() && value->IsArray(); } bool IsDate(v8::Local value) { return !value.IsEmpty() && value->IsDate(); } bool IsFunction(v8::Local value) { return !value.IsEmpty() && value->IsFunction(); } v8::Local NewNullHelper(v8::Isolate* pIsolate) { return v8::Null(pIsolate); } v8::Local NewUndefinedHelper(v8::Isolate* pIsolate) { return v8::Undefined(pIsolate); } v8::Local NewNumberHelper(v8::Isolate* pIsolate, int number) { return v8::Int32::New(pIsolate, number); } v8::Local NewNumberHelper(v8::Isolate* pIsolate, double number) { return v8::Number::New(pIsolate, number); } v8::Local NewNumberHelper(v8::Isolate* pIsolate, float number) { return v8::Number::New(pIsolate, number); } v8::Local NewBooleanHelper(v8::Isolate* pIsolate, bool b) { return v8::Boolean::New(pIsolate, b); } v8::Local NewStringHelper(v8::Isolate* pIsolate, ByteStringView str) { return v8::String::NewFromUtf8( pIsolate, str.unterminated_c_str(), v8::NewStringType::kNormal, pdfium::base::checked_cast(str.GetLength())) .ToLocalChecked(); } v8::Local NewStringHelper(v8::Isolate* pIsolate, WideStringView str) { return NewStringHelper(pIsolate, FX_UTF8Encode(str).AsStringView()); } v8::Local NewArrayHelper(v8::Isolate* pIsolate) { return v8::Array::New(pIsolate); } v8::Local NewArrayHelper(v8::Isolate* pIsolate, pdfium::span> values) { v8::Local result = NewArrayHelper(pIsolate); for (size_t i = 0; i < values.size(); ++i) { fxv8::ReentrantPutArrayElementHelper( pIsolate, result, i, values[i].IsEmpty() ? fxv8::NewUndefinedHelper(pIsolate) : values[i]); } return result; } v8::Local NewObjectHelper(v8::Isolate* pIsolate) { return v8::Object::New(pIsolate); } v8::Local NewDateHelper(v8::Isolate* pIsolate, double d) { return v8::Date::New(pIsolate->GetCurrentContext(), d) .ToLocalChecked() .As(); } WideString ToWideString(v8::Isolate* pIsolate, v8::Local pValue) { v8::String::Utf8Value s(pIsolate, pValue); return WideString::FromUTF8(ByteStringView(*s, s.length())); } ByteString ToByteString(v8::Isolate* pIsolate, v8::Local pValue) { v8::String::Utf8Value s(pIsolate, pValue); return ByteString(*s, s.length()); } int ReentrantToInt32Helper(v8::Isolate* pIsolate, v8::Local pValue) { if (pValue.IsEmpty()) return 0; v8::TryCatch squash_exceptions(pIsolate); return pValue->Int32Value(pIsolate->GetCurrentContext()).FromMaybe(0); } bool ReentrantToBooleanHelper(v8::Isolate* pIsolate, v8::Local pValue) { if (pValue.IsEmpty()) return false; v8::TryCatch squash_exceptions(pIsolate); return pValue->BooleanValue(pIsolate); } float ReentrantToFloatHelper(v8::Isolate* pIsolate, v8::Local pValue) { return static_cast(ReentrantToDoubleHelper(pIsolate, pValue)); } double ReentrantToDoubleHelper(v8::Isolate* pIsolate, v8::Local pValue) { if (pValue.IsEmpty()) return 0.0; v8::TryCatch squash_exceptions(pIsolate); return pValue->NumberValue(pIsolate->GetCurrentContext()).FromMaybe(0.0); } WideString ReentrantToWideStringHelper(v8::Isolate* pIsolate, v8::Local pValue) { if (pValue.IsEmpty()) return WideString(); v8::TryCatch squash_exceptions(pIsolate); v8::MaybeLocal maybe_string = pValue->ToString(pIsolate->GetCurrentContext()); if (maybe_string.IsEmpty()) return WideString(); return ToWideString(pIsolate, maybe_string.ToLocalChecked()); } ByteString ReentrantToByteStringHelper(v8::Isolate* pIsolate, v8::Local pValue) { if (pValue.IsEmpty()) return ByteString(); v8::TryCatch squash_exceptions(pIsolate); v8::MaybeLocal maybe_string = pValue->ToString(pIsolate->GetCurrentContext()); if (maybe_string.IsEmpty()) return ByteString(); return ToByteString(pIsolate, maybe_string.ToLocalChecked()); } v8::Local ReentrantToObjectHelper(v8::Isolate* pIsolate, v8::Local pValue) { if (!fxv8::IsObject(pValue)) return v8::Local(); v8::TryCatch squash_exceptions(pIsolate); v8::Local context = pIsolate->GetCurrentContext(); return pValue->ToObject(context).ToLocalChecked(); } v8::Local ReentrantToArrayHelper(v8::Isolate* pIsolate, v8::Local pValue) { if (!fxv8::IsArray(pValue)) return v8::Local(); v8::TryCatch squash_exceptions(pIsolate); v8::Local context = pIsolate->GetCurrentContext(); return v8::Local::Cast(pValue->ToObject(context).ToLocalChecked()); } v8::Local ReentrantGetObjectPropertyHelper( v8::Isolate* pIsolate, v8::Local pObj, ByteStringView bsUTF8PropertyName) { if (pObj.IsEmpty()) return v8::Local(); v8::TryCatch squash_exceptions(pIsolate); v8::Local val; if (!pObj->Get(pIsolate->GetCurrentContext(), NewStringHelper(pIsolate, bsUTF8PropertyName)) .ToLocal(&val)) { return v8::Local(); } return val; } std::vector ReentrantGetObjectPropertyNamesHelper( v8::Isolate* pIsolate, v8::Local pObj) { if (pObj.IsEmpty()) return std::vector(); v8::TryCatch squash_exceptions(pIsolate); v8::Local val; v8::Local context = pIsolate->GetCurrentContext(); if (!pObj->GetPropertyNames(context).ToLocal(&val)) return std::vector(); std::vector result; for (uint32_t i = 0; i < val->Length(); ++i) { result.push_back(ReentrantToWideStringHelper( pIsolate, val->Get(context, i).ToLocalChecked())); } return result; } bool ReentrantHasObjectOwnPropertyHelper(v8::Isolate* pIsolate, v8::Local pObj, ByteStringView bsUTF8PropertyName) { if (pObj.IsEmpty()) return false; v8::TryCatch squash_exceptions(pIsolate); v8::Local pContext = pIsolate->GetCurrentContext(); v8::Local hKey = fxv8::NewStringHelper(pIsolate, bsUTF8PropertyName); return pObj->HasRealNamedProperty(pContext, hKey).FromJust(); } bool ReentrantSetObjectOwnPropertyHelper(v8::Isolate* pIsolate, v8::Local pObj, ByteStringView bsUTF8PropertyName, v8::Local pValue) { if (pObj.IsEmpty() || pValue.IsEmpty()) return false; v8::TryCatch squash_exceptions(pIsolate); v8::Local name = NewStringHelper(pIsolate, bsUTF8PropertyName); return pObj->DefineOwnProperty(pIsolate->GetCurrentContext(), name, pValue) .FromMaybe(false); } bool ReentrantPutObjectPropertyHelper(v8::Isolate* pIsolate, v8::Local pObj, ByteStringView bsUTF8PropertyName, v8::Local pPut) { if (pObj.IsEmpty() || pPut.IsEmpty()) return false; v8::TryCatch squash_exceptions(pIsolate); v8::Local name = NewStringHelper(pIsolate, bsUTF8PropertyName); v8::Maybe result = pObj->Set(pIsolate->GetCurrentContext(), name, pPut); return result.IsJust() && result.FromJust(); } void ReentrantDeleteObjectPropertyHelper(v8::Isolate* pIsolate, v8::Local pObj, ByteStringView bsUTF8PropertyName) { v8::TryCatch squash_exceptions(pIsolate); pObj->Delete(pIsolate->GetCurrentContext(), fxv8::NewStringHelper(pIsolate, bsUTF8PropertyName)) .FromJust(); } bool ReentrantPutArrayElementHelper(v8::Isolate* pIsolate, v8::Local pArray, size_t index, v8::Local pValue) { if (pArray.IsEmpty()) return false; v8::TryCatch squash_exceptions(pIsolate); v8::Maybe result = pArray->Set(pIsolate->GetCurrentContext(), pdfium::base::checked_cast(index), pValue); return result.IsJust() && result.FromJust(); } v8::Local ReentrantGetArrayElementHelper(v8::Isolate* pIsolate, v8::Local pArray, size_t index) { if (pArray.IsEmpty()) return v8::Local(); v8::TryCatch squash_exceptions(pIsolate); v8::Local val; if (!pArray ->Get(pIsolate->GetCurrentContext(), pdfium::base::checked_cast(index)) .ToLocal(&val)) { return v8::Local(); } return val; } size_t GetArrayLengthHelper(v8::Local pArray) { if (pArray.IsEmpty()) return 0; return pArray->Length(); } void ThrowExceptionHelper(v8::Isolate* pIsolate, ByteStringView str) { pIsolate->ThrowException(NewStringHelper(pIsolate, str)); } void ThrowExceptionHelper(v8::Isolate* pIsolate, WideStringView str) { pIsolate->ThrowException(NewStringHelper(pIsolate, str)); } } // namespace fxv8