Check whether key exists in Dictionary::Get

This commit is contained in:
Cheng Zhao 2015-09-10 15:57:30 +08:00
parent 8ca005eb41
commit b7387da085
2 changed files with 91 additions and 10 deletions

View file

@ -15,6 +15,20 @@
namespace mate { namespace mate {
template<typename KeyType>
bool SetProperty(v8::Isolate* isolate,
v8::Local<v8::Object> object,
KeyType key,
v8::Local<v8::Value> value) {
auto maybe = object->Set(isolate->GetCurrentContext(), key, value);
return !maybe.IsNothing() && maybe.FromJust();
}
template<typename T>
struct ToV8ReturnsMaybe {
static const bool value = false;
};
template<typename T, typename Enable = void> template<typename T, typename Enable = void>
struct Converter {}; struct Converter {};
@ -241,18 +255,59 @@ struct Converter<std::set<T> > {
} }
}; };
template<typename T>
struct ToV8ReturnsMaybe<std::vector<T>> {
static const bool value = true;
};
// Convenience functions that deduce T. // Convenience functions that deduce T.
template<typename T> template<typename T>
v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate, v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate, const T& input) {
const T& input) {
return Converter<T>::ToV8(isolate, input); return Converter<T>::ToV8(isolate, input);
} }
inline v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate, inline v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate,
const char* input) { const char* input) {
return Converter<const char*>::ToV8(isolate, input); return Converter<const char*>::ToV8(isolate, input);
} }
template<typename T>
v8::MaybeLocal<v8::Value> ConvertToV8(v8::Local<v8::Context> context,
const T& input) {
return Converter<T>::ToV8(context, input);
}
template<typename T, bool = ToV8ReturnsMaybe<T>::value> struct ToV8Traits;
template <typename T>
struct ToV8Traits<T, true> {
static bool TryConvertToV8(v8::Isolate* isolate,
const T& input,
v8::Local<v8::Value>* output) {
auto maybe = ConvertToV8(isolate->GetCurrentContext(), input);
if (maybe.IsEmpty())
return false;
*output = maybe.ToLocalChecked();
return true;
}
};
template <typename T>
struct ToV8Traits<T, false> {
static bool TryConvertToV8(v8::Isolate* isolate,
const T& input,
v8::Local<v8::Value>* output) {
*output = ConvertToV8(isolate, input);
return true;
}
};
template <typename T>
bool TryConvertToV8(v8::Isolate* isolate,
T input,
v8::Local<v8::Value>* output) {
return ToV8Traits<T>::TryConvertToV8(isolate, input, output);
}
inline v8::Local<v8::String> StringToV8( inline v8::Local<v8::String> StringToV8(
v8::Isolate* isolate, v8::Isolate* isolate,
const base::StringPiece& input) { const base::StringPiece& input) {

View file

@ -10,6 +10,15 @@
namespace mate { namespace mate {
namespace internal {
// Returns true if |maybe| is both a value, and that value is true.
inline bool IsTrue(v8::Maybe<bool> maybe) {
return maybe.IsJust() && maybe.FromJust();
}
} // namespace internal
// Dictionary is useful when writing bindings for a function that either // Dictionary is useful when writing bindings for a function that either
// receives an arbitrary JavaScript object as an argument or returns an // receives an arbitrary JavaScript object as an argument or returns an
// arbitrary JavaScript object as a result. For example, Dictionary is useful // arbitrary JavaScript object as a result. For example, Dictionary is useful
@ -32,27 +41,44 @@ class Dictionary {
template<typename T> template<typename T>
bool Get(const base::StringPiece& key, T* out) const { bool Get(const base::StringPiece& key, T* out) const {
v8::Local<v8::Value> val = GetHandle()->Get(StringToV8(isolate_, key)); // Check for existence before getting, otherwise this method will always
// returns true when T == v8::Local<v8::Value>.
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
v8::Local<v8::String> v8_key = StringToV8(isolate_, key);
if (!internal::IsTrue(GetHandle()->Has(context, v8_key)))
return false;
v8::Local<v8::Value> val;
if (!GetHandle()->Get(context, v8_key).ToLocal(&val))
return false;
return ConvertFromV8(isolate_, val, out); return ConvertFromV8(isolate_, val, out);
} }
template<typename T> template<typename T>
bool GetHidden(const base::StringPiece& key, T* out) const { bool GetHidden(const base::StringPiece& key, T* out) const {
v8::Local<v8::Value> val = GetHandle()->GetHiddenValue( v8::Local<v8::Value> val =
StringToV8(isolate_, key)); GetHandle()->GetHiddenValue(StringToV8(isolate_, key));
return ConvertFromV8(isolate_, val, out); return ConvertFromV8(isolate_, val, out);
} }
template<typename T> template<typename T>
bool Set(const base::StringPiece& key, T val) { bool Set(const base::StringPiece& key, T val) {
return GetHandle()->Set(StringToV8(isolate_, key), v8::Local<v8::Value> v8_value;
ConvertToV8(isolate_, val)); if (!TryConvertToV8(isolate_, val, &v8_value))
return false;
v8::Maybe<bool> result =
GetHandle()->Set(isolate_->GetCurrentContext(),
StringToV8(isolate_, key),
v8_value);
return !result.IsNothing() && result.FromJust();
} }
template<typename T> template<typename T>
bool SetHidden(const base::StringPiece& key, T val) { bool SetHidden(const base::StringPiece& key, T val) {
return GetHandle()->SetHiddenValue(StringToV8(isolate_, key), v8::Local<v8::Value> v8_value;
ConvertToV8(isolate_, val)); if (!TryConvertToV8(isolate_, val, &v8_value))
return false;
return GetHandle()->SetHiddenValue(StringToV8(isolate_, key), v8_value);
} }
template<typename T> template<typename T>