Skip to content

Commit 9079cb9

Browse files
tgoynekneth
authored andcommitted
Don't use Nan::SetNamedPropertyHandler (#2172)
Nan's wrapper for these functions incorrectly asserts that the property name argument is a `v8::String`, while it's actually a `v8::Name` (a superclass of String) and depending on the whim of the optimizer it may be a different concrete subclass. This resulted in the realm-js-private tests (and some non-test code) crashing with the error "FATAL ERROR: v8::String::Cast Could not convert to string" when run with a debug build of the library. Fortunately the last time this API changed was in node 0.12 so there's no actual need to use Nan's wrapper.
1 parent b7fbf51 commit 9079cb9

File tree

4 files changed

+12
-10
lines changed

4 files changed

+12
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ x.x.x Release notes (yyyy-MM-dd)
66
### Fixed
77
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?)
88
* ReactNative for Android no longer uses deprecated methods and can build using Gradle 5.0 and above. ([#1995](https://github.com/realm/realm-js/issues/1995))
9+
* Fix occasional "FATAL ERROR: v8::String::Cast Could not convert to string" crashes when reading a property from a Realm object. ([#2172](https://github.com/realm/realm-js/pull/2172), since 2.19.0)
910

1011
### Compatibility
1112
* Realm Object Server: 3.11.0 or later.

src/node/node_class.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class ObjectWrap : public Nan::ObjectWrap {
8383
static void setup_property(v8::Local<TargetType>, const std::string &, const PropertyType &);
8484

8585
static void get_indexes(const Nan::PropertyCallbackInfo<v8::Array>&);
86-
static void set_property(v8::Local<v8::String>, v8::Local<v8::Value>, const Nan::PropertyCallbackInfo<v8::Value>&);
86+
static void set_property(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);
8787

8888
static void set_readonly_property(v8::Local<v8::String> property, v8::Local<v8::Value> value, const Nan::PropertyCallbackInfo<void>& info) {
8989
std::string message = std::string("Cannot assign to read only property '") + std::string(String(property)) + "'";
@@ -95,7 +95,7 @@ class ObjectWrap : public Nan::ObjectWrap {
9595
Nan::ThrowError(message.c_str());
9696
}
9797

98-
static void get_nonexistent_property(v8::Local<v8::String>, const Nan::PropertyCallbackInfo<v8::Value>&) {
98+
static void get_nonexistent_property(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&) {
9999
// Do nothing. This function exists only to prevent a crash where it is used.
100100
}
101101
};
@@ -188,7 +188,7 @@ inline v8::Local<v8::FunctionTemplate> ObjectWrap<ClassType>::create_template()
188188
if (s_class.string_accessor.getter || s_class.index_accessor.getter || s_class.index_accessor.setter) {
189189
// Use our own wrapper for the setter since we want to throw for negative indices.
190190
auto &string_accessor = s_class.string_accessor;
191-
Nan::SetNamedPropertyHandler(instance_tpl, string_accessor.getter ? string_accessor.getter : get_nonexistent_property, set_property, 0, 0, string_accessor.enumerator);
191+
instance_tpl->SetNamedPropertyHandler(string_accessor.getter ? string_accessor.getter : get_nonexistent_property, set_property, 0, 0, string_accessor.enumerator);
192192
}
193193

194194
return scope.Escape(tpl);
@@ -270,7 +270,7 @@ inline void ObjectWrap<ClassType>::get_indexes(const Nan::PropertyCallbackInfo<v
270270
}
271271

272272
template<typename ClassType>
273-
inline void ObjectWrap<ClassType>::set_property(v8::Local<v8::String> property, v8::Local<v8::Value> value, const Nan::PropertyCallbackInfo<v8::Value>& info) {
273+
inline void ObjectWrap<ClassType>::set_property(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
274274
if (s_class.index_accessor.getter || s_class.index_accessor.setter) {
275275
try {
276276
// Negative indices are passed into this string property interceptor, so check for them here.
@@ -366,7 +366,7 @@ void wrap(uint32_t index, v8::Local<v8::Value> value, const Nan::PropertyCallbac
366366
}
367367

368368
template<node::StringPropertyType::GetterType F>
369-
void wrap(v8::Local<v8::String> property, const Nan::PropertyCallbackInfo<v8::Value>& info) {
369+
void wrap(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
370370
v8::Isolate* isolate = info.GetIsolate();
371371
node::ReturnValue return_value(info.GetReturnValue());
372372
try {
@@ -378,7 +378,7 @@ void wrap(v8::Local<v8::String> property, const Nan::PropertyCallbackInfo<v8::Va
378378
}
379379

380380
template<node::StringPropertyType::SetterType F>
381-
void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, const Nan::PropertyCallbackInfo<v8::Value>& info) {
381+
void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) {
382382
v8::Isolate* isolate = info.GetIsolate();
383383
try {
384384
if (F(isolate, info.This(), property, value)) {
@@ -392,7 +392,7 @@ void wrap(v8::Local<v8::String> property, v8::Local<v8::Value> value, const Nan:
392392
}
393393

394394
template<node::StringPropertyType::EnumeratorType F>
395-
void wrap(const Nan::PropertyCallbackInfo<v8::Array>& info) {
395+
void wrap(const v8::PropertyCallbackInfo<v8::Array>& info) {
396396
auto names = F(info.GetIsolate(), info.This());
397397
int count = (int)names.size();
398398
v8::Local<v8::Array> array = Nan::New<v8::Array>(count);

src/node/node_return_value.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class ReturnValue<node::Types> {
2929

3030
public:
3131
ReturnValue(Nan::ReturnValue<v8::Value> value) : m_value(value) {}
32+
ReturnValue(v8::ReturnValue<v8::Value> value) : m_value(value) {}
3233

3334
void set(const v8::Local<v8::Value> &value) {
3435
m_value.Set(value);

src/node/node_types.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ struct Types {
4949
using PropertySetterCallback = Nan::SetterCallback;
5050
using IndexPropertyGetterCallback = Nan::IndexGetterCallback;
5151
using IndexPropertySetterCallback = Nan::IndexSetterCallback;
52-
using StringPropertyGetterCallback = Nan::PropertyGetterCallback;
53-
using StringPropertySetterCallback = Nan::PropertySetterCallback;
54-
using StringPropertyEnumeratorCallback = Nan::PropertyEnumeratorCallback;
52+
using StringPropertyGetterCallback = v8::NamedPropertyGetterCallback;
53+
using StringPropertySetterCallback = v8::NamedPropertySetterCallback;
54+
using StringPropertyEnumeratorCallback = v8::NamedPropertyEnumeratorCallback;
5555
};
5656

5757
template<typename ClassType>

0 commit comments

Comments
 (0)