Skip to content

Commit

Permalink
Merge pull request #248 from agnat/fix/add_function_and_object_templa…
Browse files Browse the repository at this point in the history
…te_factories

Add function and object template factories
  • Loading branch information
kkoopa committed Jan 22, 2015
2 parents 78d9a38 + 57d3181 commit e8eeb80
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 34 deletions.
48 changes: 35 additions & 13 deletions nan.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,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 @@ -1716,6 +1724,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 @@ -1730,23 +1762,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 @@ -62,14 +62,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 @@ -120,6 +132,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 @@ -191,11 +210,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 @@ -67,13 +67,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 @@ -122,6 +138,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 @@ -67,6 +67,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 @@ -110,6 +118,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 @@ -139,11 +152,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 @@ -209,12 +218,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 @@ -284,11 +307,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 @@ -124,6 +124,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 @@ -192,6 +204,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 @@ -355,9 +389,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 @@ -412,9 +448,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();
});

0 comments on commit e8eeb80

Please sign in to comment.