Commit 2fc51d9c authored by dcarney's avatar dcarney Committed by Commit bot

Convert v8::Value::To* to use MaybeLocal

BUG=v8:3929
LOG=y

Review URL: https://codereview.chromium.org/962983002

Cr-Commit-Position: refs/heads/master@{#26912}
parent 936ae2b8
......@@ -106,6 +106,8 @@ class Utils;
class Value;
template <class T> class Handle;
template <class T> class Local;
template <class T>
class MaybeLocal;
template <class T> class Eternal;
template<class T> class NonCopyablePersistentTraits;
template<class T> class PersistentBase;
......@@ -322,6 +324,8 @@ template <class T> class Handle {
template<class F> friend class PersistentBase;
template<class F> friend class Handle;
template<class F> friend class Local;
template <class F>
friend class MaybeLocal;
template<class F> friend class FunctionCallbackInfo;
template<class F> friend class PropertyCallbackInfo;
template<class F> friend class internal::CustomArguments;
......@@ -399,6 +403,8 @@ template <class T> class Local : public Handle<T> {
template<class F, class M> friend class Persistent;
template<class F> friend class Handle;
template<class F> friend class Local;
template <class F>
friend class MaybeLocal;
template<class F> friend class FunctionCallbackInfo;
template<class F> friend class PropertyCallbackInfo;
friend class String;
......@@ -416,6 +422,39 @@ template <class T> class Local : public Handle<T> {
};
template <class T>
class MaybeLocal {
public:
V8_INLINE MaybeLocal() : val_(nullptr) {}
template <class S>
V8_INLINE MaybeLocal(Local<S> that)
: val_(reinterpret_cast<T*>(*that)) {
TYPE_CHECK(T, S);
}
V8_INLINE bool IsEmpty() { return val_ == nullptr; }
template <class S>
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local<S>* out) const {
if (val_ == NULL) {
out->val_ = nullptr;
return false;
} else {
out->val_ = this->val_;
return true;
}
}
V8_INLINE Local<T> ToLocalChecked() {
// TODO(dcarney): add DCHECK.
return Local<T>(val_);
}
private:
T* val_;
};
// Eternal handles are set-once handles that live for the life of the isolate.
template <class T> class Eternal {
public:
......@@ -1847,6 +1886,16 @@ class V8_EXPORT Value : public Data {
*/
bool IsDataView() const;
MaybeLocal<Boolean> ToBoolean(Local<Context> context) const;
MaybeLocal<Number> ToNumber(Local<Context> context) const;
MaybeLocal<String> ToString(Local<Context> context) const;
MaybeLocal<String> ToDetailString(Local<Context> context) const;
MaybeLocal<Object> ToObject(Local<Context> context) const;
MaybeLocal<Integer> ToInteger(Local<Context> context) const;
MaybeLocal<Uint32> ToUint32(Local<Context> context) const;
MaybeLocal<Int32> ToInt32(Local<Context> context) const;
// TODO(dcarney): deprecate all these.
Local<Boolean> ToBoolean(Isolate* isolate) const;
Local<Number> ToNumber(Isolate* isolate) const;
Local<String> ToString(Isolate* isolate) const;
......@@ -1856,7 +1905,7 @@ class V8_EXPORT Value : public Data {
Local<Uint32> ToUint32(Isolate* isolate) const;
Local<Int32> ToInt32(Isolate* isolate) const;
// TODO(dcarney): deprecate all these.
// TODO(dcarney): deprecate all these as well.
inline Local<Boolean> ToBoolean() const;
inline Local<Number> ToNumber() const;
inline Local<String> ToString() const;
......
......@@ -421,4 +421,13 @@ namespace v8 { template <typename T> class AlignOfHelper { char c; T t; }; }
# define V8_ALIGNOF(type) (sizeof(::v8::AlignOfHelper<type>) - sizeof(type))
#endif
// Annotate a function indicating the caller must examine the return value.
// Use like:
// int foo() WARN_UNUSED_RESULT;
#if V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT
#define V8_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define V8_WARN_UNUSED_RESULT /* NOT SUPPORTED */
#endif
#endif // V8CONFIG_H_
......@@ -2627,108 +2627,160 @@ bool Value::IsSetIterator() const {
}
Local<String> Value::ToString(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> str;
if (obj->IsString()) {
str = obj;
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToString");
#define CONTEXT_SCOPE_GET_ISOLATE(context, function_name) \
v8::Context::Scope context_scope(context); \
auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate()); \
LOG_API(isolate, function_name); \
ENTER_V8(isolate);
#define RETURN_TO_LOCAL_UNCHECKED(maybe_local, T) \
do { \
Local<T> result; \
bool ignored = maybe_local.ToLocal(&result); \
USE(ignored); \
return result; \
} while (false);
MaybeLocal<String> Value::ToString(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsString()) return ToApiHandle<String>(obj);
CONTEXT_SCOPE_GET_ISOLATE(context, "ToString");
EXCEPTION_PREAMBLE(isolate);
has_pending_exception = !i::Execution::ToString(
isolate, obj).ToHandle(&str);
EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
}
return ToApiHandle<String>(str);
Local<String> result;
has_pending_exception =
!ToLocal<String>(i::Execution::ToString(isolate, obj), &result);
EXCEPTION_BAILOUT_CHECK(isolate, result);
return result;
}
Local<String> Value::ToDetailString(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> str;
if (obj->IsString()) {
str = obj;
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToDetailString");
ENTER_V8(isolate);
Local<String> Value::ToString(Isolate* isolate) const {
RETURN_TO_LOCAL_UNCHECKED(ToString(isolate->GetCurrentContext()), String);
}
MaybeLocal<String> Value::ToDetailString(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsString()) return ToApiHandle<String>(obj);
CONTEXT_SCOPE_GET_ISOLATE(context, "ToDetailString");
EXCEPTION_PREAMBLE(isolate);
has_pending_exception = !i::Execution::ToDetailString(
isolate, obj).ToHandle(&str);
EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
}
return ToApiHandle<String>(str);
Local<String> result;
has_pending_exception =
!ToLocal<String>(i::Execution::ToDetailString(isolate, obj), &result);
EXCEPTION_BAILOUT_CHECK(isolate, result);
return result;
}
Local<v8::Object> Value::ToObject(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> val;
if (obj->IsJSObject()) {
val = obj;
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToObject");
ENTER_V8(isolate);
Local<String> Value::ToDetailString(Isolate* isolate) const {
RETURN_TO_LOCAL_UNCHECKED(ToDetailString(isolate->GetCurrentContext()),
String);
}
MaybeLocal<Object> Value::ToObject(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsJSObject()) return ToApiHandle<Object>(obj);
CONTEXT_SCOPE_GET_ISOLATE(context, "ToObject");
EXCEPTION_PREAMBLE(isolate);
has_pending_exception = !i::Execution::ToObject(
isolate, obj).ToHandle(&val);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
}
return ToApiHandle<Object>(val);
Local<Object> result;
has_pending_exception =
!ToLocal<Object>(i::Execution::ToObject(isolate, obj), &result);
EXCEPTION_BAILOUT_CHECK(isolate, result);
return result;
}
Local<Boolean> Value::ToBoolean(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
if (obj->IsBoolean()) {
return ToApiHandle<Boolean>(obj);
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToBoolean");
ENTER_V8(isolate);
i::Handle<i::Object> val =
isolate->factory()->ToBoolean(obj->BooleanValue());
Local<v8::Object> Value::ToObject(Isolate* isolate) const {
RETURN_TO_LOCAL_UNCHECKED(ToObject(isolate->GetCurrentContext()), Object);
}
MaybeLocal<Boolean> Value::ToBoolean(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsBoolean()) return ToApiHandle<Boolean>(obj);
auto isolate = reinterpret_cast<i::Isolate*>(context->GetIsolate());
auto val = isolate->factory()->ToBoolean(obj->BooleanValue());
return ToApiHandle<Boolean>(val);
}
}
Local<Number> Value::ToNumber(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> num;
if (obj->IsNumber()) {
num = obj;
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToNumber");
ENTER_V8(isolate);
Local<Boolean> Value::ToBoolean(Isolate* v8_isolate) const {
return ToBoolean(v8_isolate->GetCurrentContext()).ToLocalChecked();
}
MaybeLocal<Number> Value::ToNumber(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsNumber()) return ToApiHandle<Number>(obj);
CONTEXT_SCOPE_GET_ISOLATE(context, "ToNumber");
EXCEPTION_PREAMBLE(isolate);
has_pending_exception = !i::Execution::ToNumber(
isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
}
return ToApiHandle<Number>(num);
Local<Number> result;
has_pending_exception =
!ToLocal<Number>(i::Execution::ToNumber(isolate, obj), &result);
EXCEPTION_BAILOUT_CHECK(isolate, result);
return result;
}
Local<Integer> Value::ToInteger(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> num;
if (obj->IsSmi()) {
num = obj;
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToInteger");
ENTER_V8(isolate);
Local<Number> Value::ToNumber(Isolate* isolate) const {
RETURN_TO_LOCAL_UNCHECKED(ToNumber(isolate->GetCurrentContext()), Number);
}
MaybeLocal<Integer> Value::ToInteger(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsSmi()) return ToApiHandle<Integer>(obj);
CONTEXT_SCOPE_GET_ISOLATE(context, "ToInteger");
EXCEPTION_PREAMBLE(isolate);
has_pending_exception = !i::Execution::ToInteger(
isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
}
return ToApiHandle<Integer>(num);
Local<Integer> result;
has_pending_exception =
!ToLocal<Integer>(i::Execution::ToInteger(isolate, obj), &result);
EXCEPTION_BAILOUT_CHECK(isolate, result);
return result;
}
Local<Integer> Value::ToInteger(Isolate* isolate) const {
RETURN_TO_LOCAL_UNCHECKED(ToInteger(isolate->GetCurrentContext()), Integer);
}
MaybeLocal<Int32> Value::ToInt32(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsSmi()) return ToApiHandle<Int32>(obj);
CONTEXT_SCOPE_GET_ISOLATE(context, "ToInt32");
EXCEPTION_PREAMBLE(isolate);
Local<Int32> result;
has_pending_exception =
!ToLocal<Int32>(i::Execution::ToInt32(isolate, obj), &result);
EXCEPTION_BAILOUT_CHECK(isolate, result);
return result;
}
Local<Int32> Value::ToInt32(Isolate* isolate) const {
RETURN_TO_LOCAL_UNCHECKED(ToInt32(isolate->GetCurrentContext()), Int32);
}
MaybeLocal<Uint32> Value::ToUint32(Local<Context> context) const {
auto obj = Utils::OpenHandle(this);
if (obj->IsSmi()) return ToApiHandle<Uint32>(obj);
CONTEXT_SCOPE_GET_ISOLATE(context, "ToUInt32");
EXCEPTION_PREAMBLE(isolate);
Local<Uint32> result;
has_pending_exception =
!ToLocal<Uint32>(i::Execution::ToUint32(isolate, obj), &result);
EXCEPTION_BAILOUT_CHECK(isolate, result);
return result;
}
Local<Uint32> Value::ToUint32(Isolate* isolate) const {
RETURN_TO_LOCAL_UNCHECKED(ToUint32(isolate->GetCurrentContext()), Uint32);
}
......@@ -2982,41 +3034,6 @@ int64_t Value::IntegerValue() const {
}
Local<Int32> Value::ToInt32(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> num;
if (obj->IsSmi()) {
num = obj;
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToInt32");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
}
return ToApiHandle<Int32>(num);
}
Local<Uint32> Value::ToUint32(Isolate* v8_isolate) const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> num;
if (obj->IsSmi()) {
num = obj;
} else {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
LOG_API(isolate, "ToUInt32");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
has_pending_exception = !i::Execution::ToUint32(
isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
}
return ToApiHandle<Uint32>(num);
}
Local<Uint32> Value::ToArrayIndex() const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
if (obj->IsSmi()) {
......
......@@ -319,6 +319,18 @@ inline v8::Local<T> ToApiHandle(
}
template <class T>
inline bool ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe,
Local<T>* local) {
v8::internal::Handle<v8::internal::Object> handle;
if (maybe.ToHandle(&handle)) {
*local = Utils::Convert<v8::internal::Object, T>(handle);
return true;
}
return false;
}
// Implementations of ToLocal
#define MAKE_TO_LOCAL(Name, From, To) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment