Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing methods to Nan::Maybe<T> #852

Merged
merged 2 commits into from May 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Expand Up @@ -55,6 +55,7 @@ LINT_SOURCES = \
test/cpp/json-parse.cpp \
test/cpp/json-stringify.cpp \
test/cpp/makecallback.cpp \
test/cpp/maybe.cpp \
test/cpp/morenews.cpp \
test/cpp/multifile1.cpp \
test/cpp/multifile2.cpp \
Expand Down
67 changes: 66 additions & 1 deletion nan.h
Expand Up @@ -213,6 +213,70 @@ template<typename T, typename M = NonCopyablePersistentTraits<T> >
class Persistent;
#endif // NODE_MODULE_VERSION

template<typename T>
class Maybe {
public:
inline bool IsNothing() const { return !has_value_; }
inline bool IsJust() const { return has_value_; }

inline T ToChecked() const { return FromJust(); }
inline void Check() const { FromJust(); }

inline bool To(T* out) const {
if (IsJust()) *out = value_;
return IsJust();
}

inline T FromJust() const {
#if defined(V8_ENABLE_CHECKS)
assert(IsJust() && "FromJust is Nothing");
#endif // V8_ENABLE_CHECKS
return value_;
}

inline T FromMaybe(const T& default_value) const {
return has_value_ ? value_ : default_value;
}

inline bool operator==(const Maybe &other) const {
return (IsJust() == other.IsJust()) &&
(!IsJust() || FromJust() == other.FromJust());
}

inline bool operator!=(const Maybe &other) const {
return !operator==(other);
}

#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
(V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
// Allow implicit conversions from v8::Maybe<T> to Nan::Maybe<T>.
Maybe(const v8::Maybe<T>& that) // NOLINT(runtime/explicit)
: has_value_(that.IsJust())
, value_(that.FromMaybe(T())) {}
#endif

private:
Maybe() : has_value_(false) {}
explicit Maybe(const T& t) : has_value_(true), value_(t) {}
bool has_value_;
T value_;

template<typename U>
friend Maybe<U> Nothing();
template<typename U>
friend Maybe<U> Just(const U& u);
};

template<typename T>
inline Maybe<T> Nothing() {
return Maybe<T>();
}

template<typename T>
inline Maybe<T> Just(const T& t) {
return Maybe<T>(t);
}

#if defined(V8_MAJOR_VERSION) && (V8_MAJOR_VERSION > 4 || \
(V8_MAJOR_VERSION == 4 && defined(V8_MINOR_VERSION) && V8_MINOR_VERSION >= 3))
# include "nan_maybe_43_inl.h" // NOLINT(build/include)
Expand Down Expand Up @@ -1079,7 +1143,8 @@ class Utf8String {
const int flags =
v8::String::NO_NULL_TERMINATION | imp::kReplaceInvalidUtf8;
#if NODE_MAJOR_VERSION >= 11
length_ = string->WriteUtf8(v8::Isolate::GetCurrent(), str_, static_cast<int>(len), 0, flags);
length_ = string->WriteUtf8(v8::Isolate::GetCurrent(), str_,
static_cast<int>(len), 0, flags);
#else
// See https://github.com/nodejs/nan/issues/832.
// Disable the warning as there is no way around it.
Expand Down
3 changes: 2 additions & 1 deletion nan_implementation_12_inl.h
Expand Up @@ -347,7 +347,8 @@ Factory<v8::StringObject>::return_t
Factory<v8::StringObject>::New(v8::Local<v8::String> value) {
// V8 > 7.0
#if V8_MAJOR_VERSION > 7 || (V8_MAJOR_VERSION == 7 && V8_MINOR_VERSION > 0)
return v8::StringObject::New(v8::Isolate::GetCurrent(), value).As<v8::StringObject>();
return v8::StringObject::New(v8::Isolate::GetCurrent(), value)
.As<v8::StringObject>();
#else
#ifdef _MSC_VER
#pragma warning(push)
Expand Down
13 changes: 0 additions & 13 deletions nan_maybe_43_inl.h
Expand Up @@ -12,19 +12,6 @@
template<typename T>
using MaybeLocal = v8::MaybeLocal<T>;

template<typename T>
using Maybe = v8::Maybe<T>;

template<typename T>
inline Maybe<T> Nothing() {
return v8::Nothing<T>();
}

template<typename T>
inline Maybe<T> Just(const T& t) {
return v8::Just<T>(t);
}

inline
MaybeLocal<v8::String> ToDetailString(v8::Local<v8::Value> val) {
v8::Isolate *isolate = v8::Isolate::GetCurrent();
Expand Down
48 changes: 0 additions & 48 deletions nan_maybe_pre_43_inl.h
Expand Up @@ -48,54 +48,6 @@ class MaybeLocal {
v8::Local<T> val_;
};

template<typename T>
class Maybe {
public:
inline bool IsNothing() const { return !has_value_; }
inline bool IsJust() const { return has_value_; }

inline T FromJust() const {
#if defined(V8_ENABLE_CHECKS)
assert(IsJust() && "FromJust is Nothing");
#endif // V8_ENABLE_CHECKS
return value_;
}

inline T FromMaybe(const T& default_value) const {
return has_value_ ? value_ : default_value;
}

inline bool operator==(const Maybe &other) const {
return (IsJust() == other.IsJust()) &&
(!IsJust() || FromJust() == other.FromJust());
}

inline bool operator!=(const Maybe &other) const {
return !operator==(other);
}

private:
Maybe() : has_value_(false) {}
explicit Maybe(const T& t) : has_value_(true), value_(t) {}
bool has_value_;
T value_;

template<typename U>
friend Maybe<U> Nothing();
template<typename U>
friend Maybe<U> Just(const U& u);
};

template<typename T>
inline Maybe<T> Nothing() {
return Maybe<T>();
}

template<typename T>
inline Maybe<T> Just(const T& t) {
return Maybe<T>(t);
}

inline
MaybeLocal<v8::String> ToDetailString(v8::Handle<v8::Value> val) {
return MaybeLocal<v8::String>(val->ToDetailString());
Expand Down
4 changes: 4 additions & 0 deletions test/binding.gyp
Expand Up @@ -90,6 +90,10 @@
"target_name" : "makecallback"
, "sources" : [ "cpp/makecallback.cpp" ]
}
, {
"target_name" : "maybe"
, "sources" : [ "cpp/maybe.cpp" ]
}
, {
"target_name" : "asyncresource"
, "sources" : [ "cpp/asyncresource.cpp" ]
Expand Down
39 changes: 39 additions & 0 deletions test/cpp/maybe.cpp
@@ -0,0 +1,39 @@
/*********************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2019 NAN contributors
*
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
********************************************************************/

#include <nan.h>

using namespace Nan; // NOLINT(build/namespaces)

NAN_METHOD(Test) {
info.GetReturnValue().Set(false);
{
Maybe<int> mb = Nothing<int>();
if (mb.IsJust()) return;
if (!mb.IsNothing()) return;
if (mb.To(NULL)) return;
}
{
Maybe<int> mb = Just(42);
if (!mb.IsJust()) return;
if (mb.IsNothing()) return;
if (42 != mb.FromJust()) return;
if (42 != mb.ToChecked()) return;
mb.Check();
int v;
if (!mb.To(&v)) return;
if (42 != v) return;
}
info.GetReturnValue().Set(true);
}

NAN_MODULE_INIT(Init) {
SetMethod(target, "test", Test);
}

NODE_MODULE(maybe, Init)
12 changes: 8 additions & 4 deletions test/cpp/morenews.cpp
Expand Up @@ -72,11 +72,13 @@ NAN_MODULE_INIT(Init) {
);
Set(target
, New("newNegativeInteger").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewNegativeInteger)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewNegativeInteger))
.ToLocalChecked()
);
Set(target
, New("newPositiveInteger").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewPositiveInteger)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewPositiveInteger))
.ToLocalChecked()
);
Set(target
, New("newUtf8String").ToLocalChecked()
Expand All @@ -92,11 +94,13 @@ NAN_MODULE_INIT(Init) {
);
Set(target
, New("newExternalStringResource").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewExternalStringResource)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewExternalStringResource))
.ToLocalChecked()
);
Set(target
, New("newExternalAsciiStringResource").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewExternalAsciiStringResource)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewExternalAsciiStringResource))
.ToLocalChecked()
);
}

Expand Down
2 changes: 1 addition & 1 deletion test/cpp/multifile2.cpp
Expand Up @@ -7,7 +7,7 @@
********************************************************************/

#include <nan.h>
#include "multifile2.h"
#include "multifile2.h" // NOLINT(build/include)

using namespace Nan; // NOLINT(build/namespaces)

Expand Down
21 changes: 14 additions & 7 deletions test/cpp/news.cpp
Expand Up @@ -169,31 +169,38 @@ NAN_MODULE_INIT(Init) {
);
Set(target
, New<v8::String>("newNegativeInteger").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewNegativeInteger)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewNegativeInteger))
.ToLocalChecked()
);
Set(target
, New<v8::String>("newPositiveInteger").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewPositiveInteger)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewPositiveInteger))
.ToLocalChecked()
);
Set(target
, New<v8::String>("newUnsignedInteger").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewUnsignedInteger)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewUnsignedInteger))
.ToLocalChecked()
);
Set(target
, New<v8::String>("newInt32FromPositive").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewInt32FromPositive)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewInt32FromPositive))
.ToLocalChecked()
);
Set(target
, New<v8::String>("newInt32FromNegative").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewInt32FromNegative)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewInt32FromNegative))
.ToLocalChecked()
);
Set(target
, New<v8::String>("newUint32FromPositive").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewUint32FromPositive)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewUint32FromPositive))
.ToLocalChecked()
);
Set(target
, New<v8::String>("newUint32FromNegative").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewUint32FromNegative)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(NewUint32FromNegative))
.ToLocalChecked()
);
Set(target
, New<v8::String>("newUtf8String").ToLocalChecked()
Expand Down
3 changes: 2 additions & 1 deletion test/cpp/setcallhandler.cpp
Expand Up @@ -37,7 +37,8 @@ NAN_MODULE_INIT(Init) {
);
Set(target
, New("b").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(CallAsFunctionHandlerSetter)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(CallAsFunctionHandlerSetter))
.ToLocalChecked()
);
}

Expand Down
3 changes: 2 additions & 1 deletion test/cpp/threadlocal.cpp
Expand Up @@ -63,7 +63,8 @@ NAN_METHOD(thread_local_storage) {
NAN_MODULE_INIT(Init) {
Set(target
, New<v8::String>("thread_local_storage").ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(thread_local_storage)).ToLocalChecked()
, GetFunction(New<v8::FunctionTemplate>(thread_local_storage))
.ToLocalChecked()
);
}

Expand Down
16 changes: 16 additions & 0 deletions test/js/maybe-test.js
@@ -0,0 +1,16 @@
/*********************************************************************
* NAN - Native Abstractions for Node.js
*
* Copyright (c) 2019 NAN contributors
*
* MIT License <https://github.com/nodejs/nan/blob/master/LICENSE.md>
********************************************************************/

const test = require('tap').test
, testRoot = require('path').resolve(__dirname, '..')
, bindings = require('bindings')({ module_root: testRoot, bindings: 'maybe' })

test('maybe', function (t) {
t.plan(1);
t.ok(bindings.test());
});