diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2013-07-03 04:23:44 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2013-07-06 17:44:44 +0200 |
commit | 110a9cd8db515c4d1a9ac5cd8837291da7c6c5ea (patch) | |
tree | 71e5a14a98131d89d670f842eb36bfcccab00b7b /src/node_internals.h | |
parent | 9b3de60d3537df657e75887436a5b1df5ed80c2d (diff) | |
download | node-new-110a9cd8db515c4d1a9ac5cd8837291da7c6c5ea.tar.gz |
lib, src: upgrade after v8 api change
This is a big commit that touches just about every file in the src/
directory. The V8 API has changed in significant ways. The most
important changes are:
* Binding functions take a const v8::FunctionCallbackInfo<T>& argument
rather than a const v8::Arguments& argument.
* Binding functions return void rather than v8::Handle<v8::Value>. The
return value is returned with the args.GetReturnValue().Set() family
of functions.
* v8::Persistent<T> no longer derives from v8::Handle<T> and no longer
allows you to directly dereference the object that the persistent
handle points to. This means that the common pattern of caching
oft-used JS values in a persistent handle no longer quite works,
you first need to reconstruct a v8::Local<T> from the persistent
handle with the Local<T>::New(isolate, persistent) factory method.
A handful of (internal) convenience classes and functions have been
added to make dealing with the new API a little easier.
The most visible one is node::Cached<T>, which wraps a v8::Persistent<T>
with some template sugar. It can hold arbitrary types but so far it's
exclusively used for v8::Strings (which was by far the most commonly
cached handle type.)
Diffstat (limited to 'src/node_internals.h')
-rw-r--r-- | src/node_internals.h | 206 |
1 files changed, 197 insertions, 9 deletions
diff --git a/src/node_internals.h b/src/node_internals.h index 9e5e0bf92d..29c38adb0a 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -22,6 +22,7 @@ #ifndef SRC_NODE_INTERNALS_H_ #define SRC_NODE_INTERNALS_H_ +#include <assert.h> #include <stdlib.h> #include "v8.h" @@ -32,7 +33,67 @@ namespace node { extern v8::Isolate* node_isolate; // Defined in node.cc at startup. -extern v8::Persistent<v8::Object> process; +extern v8::Persistent<v8::Object> process_p; + +template <typename TypeName> +class CachedBase { +public: + CachedBase(); + operator v8::Handle<TypeName>() const; + void operator=(v8::Handle<TypeName> that); // Can only assign once. + bool IsEmpty() const; +private: + CachedBase(const CachedBase&); + void operator=(const CachedBase&); + v8::Persistent<TypeName> handle_; +}; + +template <typename TypeName> +class Cached : public CachedBase<TypeName> { +public: + operator v8::Handle<v8::Value>() const; + void operator=(v8::Handle<TypeName> that); +}; + +template <> +class Cached<v8::Value> : public CachedBase<v8::Value> { +public: + operator v8::Handle<v8::Value>() const; + void operator=(v8::Handle<v8::Value> that); +}; + +template <typename TypeName> +v8::Handle<v8::Value> MakeCallback( + const v8::Persistent<v8::Object>& recv, + const TypeName method, + int argc, + v8::Handle<v8::Value>* argv); + +template <typename TypeName> +v8::Handle<v8::Value> MakeCallback( + const v8::Persistent<v8::Object>& recv, + const Cached<TypeName>& method, + int argc, + v8::Handle<v8::Value>* argv); + +inline bool HasInstance(v8::Persistent<v8::FunctionTemplate>& function_template, + v8::Handle<v8::Value> value); + +inline v8::Local<v8::Object> NewInstance(v8::Persistent<v8::Function>& ctor, + int argc = 0, + v8::Handle<v8::Value>* argv = NULL); + +// TODO(bnoordhuis) Move to src/node_buffer.h once it's been established +// that the current approach to dealing with Persistent is working out. +namespace Buffer { + +template <typename TypeName> +inline char* Data(v8::Persistent<TypeName>& val); + +template <typename TypeName> +inline size_t Length(v8::Persistent<TypeName>& val); + +} // namespace Buffer #ifdef _WIN32 // emulate snprintf() on windows, _snprintf() doesn't zero-terminate the buffer @@ -87,22 +148,44 @@ inline static int snprintf(char* buf, unsigned int len, const char* fmt, ...) { #define THROW_ERROR(fun) \ do { \ v8::HandleScope scope(node_isolate); \ - return v8::ThrowException(fun(v8::String::New(errmsg))); \ + v8::ThrowException(fun(v8::String::New(errmsg))); \ } \ while (0) -inline static v8::Handle<v8::Value> ThrowError(const char* errmsg) { +inline static void ThrowError(const char* errmsg) { THROW_ERROR(v8::Exception::Error); } -inline static v8::Handle<v8::Value> ThrowTypeError(const char* errmsg) { +inline static void ThrowTypeError(const char* errmsg) { THROW_ERROR(v8::Exception::TypeError); } -inline static v8::Handle<v8::Value> ThrowRangeError(const char* errmsg) { +inline static void ThrowRangeError(const char* errmsg) { THROW_ERROR(v8::Exception::RangeError); } +inline static void ThrowErrnoException(int errorno, + const char* syscall = NULL, + const char* message = NULL, + const char* path = NULL) { + NODE_EXTERN v8::Local<v8::Value> ErrnoException(int errorno, + const char* syscall = NULL, + const char* message = NULL, + const char* path = NULL); + v8::ThrowException(ErrnoException(errorno, syscall, message, path)); +} + +inline static void ThrowUVException(int errorno, + const char* syscall = NULL, + const char* message = NULL, + const char* path = NULL) { + NODE_EXTERN v8::Local<v8::Value> UVException(int errorno, + const char* syscall = NULL, + const char* message = NULL, + const char* path = NULL); + v8::ThrowException(UVException(errorno, syscall, message, path)); +} + NO_RETURN void FatalError(const char* location, const char* message); #define UNWRAP(type) \ @@ -116,10 +199,6 @@ NO_RETURN void FatalError(const char* location, const char* message); abort(); \ } -v8::Handle<v8::Value> FromConstructorTemplate( - v8::Persistent<v8::FunctionTemplate> t, - const v8::Arguments& args); - // allow for quick domain check extern bool using_domains; @@ -165,6 +244,115 @@ inline MUST_USE_RESULT bool ParseArrayIndex(v8::Handle<v8::Value> arg, return true; } +template <typename TypeName> +CachedBase<TypeName>::CachedBase() { +} + +template <typename TypeName> +CachedBase<TypeName>::operator v8::Handle<TypeName>() const { + return v8::Local<TypeName>::New(node_isolate, handle_); +} + +template <typename TypeName> +void CachedBase<TypeName>::operator=(v8::Handle<TypeName> that) { + assert(handle_.IsEmpty() == true); // Can only assign once. + handle_.Reset(node_isolate, that); +} + +template <typename TypeName> +bool CachedBase<TypeName>::IsEmpty() const { + return handle_.IsEmpty(); +} + +template <typename TypeName> +Cached<TypeName>::operator v8::Handle<v8::Value>() const { + return CachedBase<TypeName>::operator v8::Handle<TypeName>(); +} + +template <typename TypeName> +void Cached<TypeName>::operator=(v8::Handle<TypeName> that) { + CachedBase<TypeName>::operator=(that); +} + +inline Cached<v8::Value>::operator v8::Handle<v8::Value>() const { + return CachedBase<v8::Value>::operator v8::Handle<v8::Value>(); +} + +inline void Cached<v8::Value>::operator=(v8::Handle<v8::Value> that) { + CachedBase<v8::Value>::operator=(that); +} + +// Forward declarations, see node.h +NODE_EXTERN v8::Handle<v8::Value> MakeCallback( + const v8::Handle<v8::Object> recv, + const char* method, + int argc, + v8::Handle<v8::Value>* argv); +NODE_EXTERN v8::Handle<v8::Value> MakeCallback( + const v8::Handle<v8::Object> object, + const v8::Handle<v8::String> symbol, + int argc, + v8::Handle<v8::Value>* argv); +NODE_EXTERN v8::Handle<v8::Value> MakeCallback( + const v8::Handle<v8::Object> object, + const v8::Handle<v8::Function> callback, + int argc, + v8::Handle<v8::Value>* argv); + +template <typename TypeName> +v8::Handle<v8::Value> MakeCallback( + const v8::Persistent<v8::Object>& recv, + const TypeName method, + int argc, + v8::Handle<v8::Value>* argv) { + v8::Local<v8::Object> recv_obj = + v8::Local<v8::Object>::New(node_isolate, recv); + return MakeCallback(recv_obj, method, argc, argv); +} + +template <typename TypeName> +v8::Handle<v8::Value> MakeCallback( + const v8::Persistent<v8::Object>& recv, + const Cached<TypeName>& method, + int argc, + v8::Handle<v8::Value>* argv) { + const v8::Handle<TypeName> handle = method; + return MakeCallback(recv, handle, argc, argv); +} + +inline bool HasInstance(v8::Persistent<v8::FunctionTemplate>& function_template, + v8::Handle<v8::Value> value) { + v8::Local<v8::FunctionTemplate> function_template_handle = + v8::Local<v8::FunctionTemplate>::New(node_isolate, function_template); + return function_template_handle->HasInstance(value); +} + +inline v8::Local<v8::Object> NewInstance(v8::Persistent<v8::Function>& ctor, + int argc, + v8::Handle<v8::Value>* argv) { + v8::Local<v8::Function> constructor_handle = + v8::Local<v8::Function>::New(node_isolate, ctor); + return constructor_handle->NewInstance(argc, argv); +} + +namespace Buffer { + +template <typename TypeName> +inline char* Data(v8::Persistent<TypeName>& val) { + NODE_EXTERN char* Data(v8::Handle<v8::Value>); + NODE_EXTERN char* Data(v8::Handle<v8::Object>); + return Data(v8::Local<TypeName>::New(node_isolate, val)); +} + +template <typename TypeName> +inline size_t Length(v8::Persistent<TypeName>& val) { + NODE_EXTERN size_t Length(v8::Handle<v8::Value>); + NODE_EXTERN size_t Length(v8::Handle<v8::Object>); + return Length(v8::Local<TypeName>::New(node_isolate, val)); +} + +} // namespace Buffer + } // namespace node #endif // SRC_NODE_INTERNALS_H_ |