Skip to content

Add function and object template factories #248

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

Merged
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 35 additions & 13 deletions nan.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ typedef v8::UnboundScript NanUnboundScript;
typedef v8::Script NanBoundScript;
#endif

#if (NODE_MODULE_VERSION < 42)
typedef v8::String::ExternalAsciiStringResource
NanExternalOneByteStringResource;
#else // io.js v1.0.0
typedef v8::String::ExternalOneByteStringResource
NanExternalOneByteStringResource;
#endif

#include "nan_new.h" // NOLINT(build/include)

// uv helpers
Expand Down Expand Up @@ -1713,6 +1721,30 @@ template<typename T> static size_t _nan_hex_decode(
return i;
}

namespace NanIntern {

inline
NanExternalOneByteStringResource const*
GetExternalResource(v8::Local<v8::String> str) {
#if NODE_MODULE_VERSION < 42
return str->GetExternalAsciiStringResource();
#else // io.js v1.0.0
return str->GetExternalOneByteStringResource();
#endif
}

inline
bool
IsExternal(v8::Local<v8::String> str) {
#if NODE_MODULE_VERSION < 42
return str->IsExternalAscii();
#else // io.js v1.0.0
return str->IsExternalOneByte();
#endif
}

} // end of namespace NanIntern

static bool _NanGetExternalParts(
v8::Handle<v8::Value> val
, const char** data
Expand All @@ -1727,23 +1759,13 @@ static bool _NanGetExternalParts(
assert(val->IsString());
v8::Local<v8::String> str = NanNew(val.As<v8::String>());

#if NODE_MODULE_VERSION >= 42 // io.js v1.0.0
if (str->IsExternalOneByte()) {
const v8::String::ExternalOneByteStringResource* ext;
ext = str->GetExternalOneByteStringResource();
if (NanIntern::IsExternal(str)) {
const NanExternalOneByteStringResource* ext;
ext = NanIntern::GetExternalResource(str);
*data = ext->data();
*len = ext->length();
return true;
}
#else
if (str->IsExternalAscii()) {
const v8::String::ExternalAsciiStringResource* ext;
ext = str->GetExternalAsciiStringResource();
*data = ext->data();
*len = ext->length();
return true;
}
#endif

if (str->IsExternal()) {
const v8::String::ExternalStringResource* ext;
Expand Down
29 changes: 22 additions & 7 deletions nan_implementation_12_inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,26 @@ Factory<v8::External>::New(void * value) {
return v8::External::New(v8::Isolate::GetCurrent(), value);
}

//=== Function =================================================================

Factory<v8::Function>::return_t
Factory<v8::Function>::New( NanFunctionCallback callback
, v8::Handle<v8::Value> data) {
return v8::Function::New( v8::Isolate::GetCurrent()
, callback
, data);
}

//=== Function Template ========================================================

Factory<v8::FunctionTemplate>::return_t
Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
, v8::Handle<v8::Value> data
, v8::Handle<v8::Signature> signature) {
return v8::FunctionTemplate::New(v8::Isolate::GetCurrent(), callback, data,
signature);
return v8::FunctionTemplate::New( v8::Isolate::GetCurrent()
, callback
, data
, signature);
}

//=== Number ===================================================================
Expand Down Expand Up @@ -114,6 +126,13 @@ Factory<v8::Object>::New() {
return v8::Object::New(v8::Isolate::GetCurrent());
}

//=== Object Template ==========================================================

Factory<v8::ObjectTemplate>::return_t
Factory<v8::ObjectTemplate>::New() {
return v8::ObjectTemplate::New(v8::Isolate::GetCurrent());
}

//=== RegExp ===================================================================

Factory<v8::RegExp>::return_t
Expand Down Expand Up @@ -184,11 +203,7 @@ Factory<v8::String>::New(v8::String::ExternalStringResource * value) {
}

Factory<v8::String>::return_t
#if NODE_MODULE_VERSION >= 42 // io.js v1.0.0
Factory<v8::String>::New(v8::String::ExternalOneByteStringResource * value) {
#else
Factory<v8::String>::New(v8::String::ExternalAsciiStringResource * value) {
#endif
Factory<v8::String>::New(NanExternalOneByteStringResource * value) {
return v8::String::NewExternal(v8::Isolate::GetCurrent(), value);
}

Expand Down
25 changes: 24 additions & 1 deletion nan_implementation_pre_12_inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,29 @@ Factory<v8::External>::New(void * value) {
return v8::External::New(value);
}

//=== Function =================================================================

Factory<v8::Function>::return_t
Factory<v8::Function>::New( NanFunctionCallback callback
, v8::Handle<v8::Value> data) {
return Factory<v8::FunctionTemplate>::New( callback
, data
, v8::Handle<v8::Signature>()
)->GetFunction();
}


//=== FunctionTemplate =========================================================

Factory<v8::FunctionTemplate>::return_t
Factory<v8::FunctionTemplate>::New( NanFunctionCallback callback
, v8::Handle<v8::Value> data
, v8::Handle<v8::Signature> signature) {
return v8::FunctionTemplate::New(callback, data, signature);
// Note(agnat): Emulate length argument here. Unfortunately, I couldn't find
// a way. Have at it though...
return v8::FunctionTemplate::New( callback
, data
, signature);
}

//=== Number ===================================================================
Expand Down Expand Up @@ -114,6 +130,13 @@ Factory<v8::Object>::New() {
return v8::Object::New();
}

//=== Object Template ==========================================================

Factory<v8::ObjectTemplate>::return_t
Factory<v8::ObjectTemplate>::New() {
return v8::ObjectTemplate::New();
}

//=== RegExp ===================================================================

Factory<v8::RegExp>::return_t
Expand Down
43 changes: 31 additions & 12 deletions nan_new.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ struct Factory<v8::External> : FactoryBase<v8::External> {
static inline return_t New(void *value);
};

template <>
struct Factory<v8::Function> : FactoryBase<v8::Function> {
static inline
return_t
New( NanFunctionCallback callback
, v8::Handle<v8::Value> data = v8::Handle<v8::Value>());
};

template <>
struct Factory<v8::FunctionTemplate> : FactoryBase<v8::FunctionTemplate> {
static inline
Expand Down Expand Up @@ -104,6 +112,11 @@ struct Factory<v8::Object> : FactoryBase<v8::Object> {
static inline return_t New();
};

template <>
struct Factory<v8::ObjectTemplate> : FactoryBase<v8::ObjectTemplate> {
static inline return_t New();
};

template <>
struct Factory<v8::RegExp> : FactoryBase<v8::RegExp> {
static inline return_t New(
Expand Down Expand Up @@ -133,11 +146,7 @@ struct Factory<v8::String> : FactoryBase<v8::String> {
static inline return_t New(std::string const& value);

static inline return_t New(v8::String::ExternalStringResource * value);
#if NODE_MODULE_VERSION >= 42 // io.js v1.0.0
static inline return_t New(v8::String::ExternalOneByteStringResource * value);
#else
static inline return_t New(v8::String::ExternalAsciiStringResource * value);
#endif
static inline return_t New(NanExternalOneByteStringResource * value);

// TODO(agnat): Deprecate.
static inline return_t New(const uint8_t * value, int length = -1);
Expand Down Expand Up @@ -203,12 +212,26 @@ NanNew(A0 arg0, A1 arg1, A2 arg2, A3 arg3) {
return NanIntern::Factory<T>::New(arg0, arg1, arg2, arg3);
}

// Note(agnat): When passing overloaded function pointers to template functions
// as generic arguments the compiler needs help in picking the right overload.
// These two functions handle NanNew<Function> and NanNew<FunctionTemplate> with
// all argument variations.

// v8::Function and v8::FunctionTemplate with one or two arguments
template <typename T>
typename NanIntern::Factory<T>::return_t
NanNew( NanFunctionCallback callback
, v8::Handle<v8::Value> data = v8::Handle<v8::Value>()) {
return NanIntern::Factory<T>::New(callback, data);
}

// v8::Function and v8::FunctionTemplate with three arguments
template <typename T, typename A2>
typename NanIntern::Factory<T>::return_t
NanNew( NanFunctionCallback callback
, v8::Handle<v8::Value> data = v8::Handle<v8::Value>()
, v8::Handle<v8::Signature> signature = v8::Handle<v8::Signature>()) {
return NanIntern::Factory<T>::New(callback, data, signature);
, A2 a2 = A2()) {
return NanIntern::Factory<T>::New(callback, data, a2);
}

// Convenience
Expand Down Expand Up @@ -278,11 +301,7 @@ NanNew(v8::String::ExternalStringResource * value) {

inline
NanIntern::Factory<v8::String>::return_t
#if NODE_MODULE_VERSION >= 42 // io.js v1.0.0
NanNew(v8::String::ExternalOneByteStringResource * value) {
#else
NanNew(v8::String::ExternalAsciiStringResource * value) {
#endif
NanNew(NanExternalOneByteStringResource * value) {
return NanNew<v8::String>(value);
}

Expand Down
41 changes: 40 additions & 1 deletion test/cpp/nannew.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ NAN_METHOD(testExternal) {
return_NanUndefined();
}

NAN_METHOD(testFunction) {
NanScope();
NanTap t(args[0]);
t.plan(2);

t.ok(_( assertType<Function>(NanNew<Function>(testFunction))));
v8::Local<String> data = NanNew("plonk");
t.ok(_( assertType<Function>(NanNew<Function>(testFunction, data))));

return_NanUndefined();
}

NAN_METHOD(testFunctionTemplate) {
NanScope();
NanTap t(args[0]);
Expand Down Expand Up @@ -185,6 +197,28 @@ NAN_METHOD(testNumberObject) {
return_NanUndefined();
}

NAN_METHOD(testObject) {
NanScope();
NanTap t(args[0]);

t.plan(1);

t.ok(_(assertType<Object>( NanNew<Object>())));

return_NanUndefined();
}

NAN_METHOD(testObjectTemplate) {
NanScope();
NanTap t(args[0]);

t.plan(1);

t.ok(_(assertType<ObjectTemplate>( NanNew<ObjectTemplate>())));

return_NanUndefined();
}

NAN_METHOD(testScript) {
NanScope();
NanTap t(args[0]);
Expand Down Expand Up @@ -342,9 +376,11 @@ NAN_METHOD(testRegression242) {
NanScope();
NanTap t(args[0]);

// This line needs to *compile*. Not much to test at runtime.
// These lines must *compile*. Not much to test at runtime.
Local<FunctionTemplate> ft = NanNew<FunctionTemplate>(overloaded);
(void)ft; // not unused
Local<Function> f = NanNew<Function>(overloaded);
(void)f; // not unused

t.plan(1);

Expand Down Expand Up @@ -399,9 +435,12 @@ void Init(Handle<Object> exports) {
NAN_EXPORT(exports, testBooleanObject);
NAN_EXPORT(exports, testDate);
NAN_EXPORT(exports, testExternal);
NAN_EXPORT(exports, testFunction);
NAN_EXPORT(exports, testFunctionTemplate);
NAN_EXPORT(exports, testNumber);
NAN_EXPORT(exports, testNumberObject);
NAN_EXPORT(exports, testObject);
NAN_EXPORT(exports, testObjectTemplate);
NAN_EXPORT(exports, testScript);
NAN_EXPORT(exports, testSignature);
NAN_EXPORT(exports, testString);
Expand Down
2 changes: 2 additions & 0 deletions test/js/nannew-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,7 @@ test('strings', function (t) {
t.equals(bindings.newStringFromChars(), "hello?");
t.equals(bindings.newStringFromCharsWithLength(), "hell");
t.equals(bindings.newStringFromStdString(), "hello!");

t.end();
});