summaryrefslogtreecommitdiff
path: root/src/node_internals.h
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-07-03 04:23:44 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2013-07-06 17:44:44 +0200
commit110a9cd8db515c4d1a9ac5cd8837291da7c6c5ea (patch)
tree71e5a14a98131d89d670f842eb36bfcccab00b7b /src/node_internals.h
parent9b3de60d3537df657e75887436a5b1df5ed80c2d (diff)
downloadnode-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.h206
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_