Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Safe constructor for ObjectWrapped classes

New() methods should be invoked as constructors, not regular functions.
Corner cases like Script::New() may cause a SIGSEGV when the GC is run.

More details: http://groups.google.com/group/nodejs/browse_thread/thread/a7e5db68d4cd6356
  • Loading branch information...
commit 55c65cc2d55b70def061da0c8fd38f08b2929433 1 parent 9911629
@bnoordhuis bnoordhuis authored ry committed
View
16 src/node.cc
@@ -787,6 +787,22 @@ Local<Value> ErrnoException(int errorno,
}
+Handle<Value> FromConstructorTemplate(Persistent<FunctionTemplate>& t,
+ const Arguments& args) {
+ HandleScope scope;
+
+ const int argc = args.Length();
+ Local<Value> argv[argc];
+
+ for (int i = 0; i < argc; ++i) {
+ argv[i] = args[i];
+ }
+
+ Local<Object> instance = t->GetFunction()->NewInstance(argc, argv);
+ return scope.Close(instance);
+}
+
+
enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
HandleScope scope;
View
9 src/node.h
@@ -65,6 +65,15 @@ ssize_t DecodeWrite(char *buf,
v8::Local<v8::Object> BuildStatsObject(struct stat * s);
+/**
+ * Call this when your constructor is invoked as a regular function, e.g. Buffer(10) instead of new Buffer(10).
+ * @param constructorTemplate Constructor template to instantiate from.
+ * @param args The arguments object passed to your constructor.
+ * @see v8::Arguments::IsConstructCall
+ */
+v8::Handle<v8::Value> FromConstructorTemplate(v8::Persistent<v8::FunctionTemplate>& constructorTemplate, const v8::Arguments& args);
+
+
static inline v8::Persistent<v8::Function>* cb_persist(
const v8::Local<v8::Value> &v) {
v8::Persistent<v8::Function> *fn = new v8::Persistent<v8::Function>();
View
12 src/node_buffer.cc
@@ -127,18 +127,12 @@ size_t Buffer::Length(Handle<Object> obj) {
Handle<Value> Buffer::New(const Arguments &args) {
- HandleScope scope;
-
if (!args.IsConstructCall()) {
- Local<Value> argv[10];
- for (int i = 0; i < MIN(args.Length(), 10); i++) {
- argv[i] = args[i];
- }
- Local<Object> instance =
- constructor_template->GetFunction()->NewInstance(args.Length(), argv);
- return scope.Close(instance);
+ return FromConstructorTemplate(constructor_template, args);
}
+ HandleScope scope;
+
Buffer *buffer;
if (args[0]->IsInt32()) {
// var buffer = new Buffer(1024);
View
4 src/node_cares.cc
@@ -459,6 +459,10 @@ void Channel::Initialize(Handle<Object> target) {
Handle<Value> Channel::New(const Arguments& args) {
+ if (!args.IsConstructCall()) {
+ return FromConstructorTemplate(constructor_template, args);
+ }
+
HandleScope scope;
struct ares_options options;
View
4 src/node_idle_watcher.cc
@@ -77,6 +77,10 @@ void IdleWatcher::Callback(EV_P_ ev_idle *w, int revents) {
// idle.start();
//
Handle<Value> IdleWatcher::New(const Arguments& args) {
+ if (!args.IsConstructCall()) {
+ return FromConstructorTemplate(constructor_template, args);
+ }
+
HandleScope scope;
IdleWatcher *s = new IdleWatcher();
View
4 src/node_io_watcher.cc
@@ -68,6 +68,10 @@ void IOWatcher::Callback(EV_P_ ev_io *w, int revents) {
// io.start();
//
Handle<Value> IOWatcher::New(const Arguments& args) {
+ if (!args.IsConstructCall()) {
+ return FromConstructorTemplate(constructor_template, args);
+ }
+
HandleScope scope;
IOWatcher *s = new IOWatcher();
s->Wrap(args.This());
View
4 src/node_script.cc
@@ -78,6 +78,10 @@ void node::Script::Initialize (Handle<Object> target) {
Handle<Value> node::Script::New (const Arguments& args) {
+ if (!args.IsConstructCall()) {
+ return FromConstructorTemplate(constructor_template, args);
+ }
+
HandleScope scope;
node::Script *t = new node::Script();
View
4 src/node_signal_watcher.cc
@@ -51,6 +51,10 @@ void SignalWatcher::Callback(EV_P_ ev_signal *watcher, int revents) {
}
Handle<Value> SignalWatcher::New(const Arguments& args) {
+ if (!args.IsConstructCall()) {
+ return FromConstructorTemplate(constructor_template, args);
+ }
+
HandleScope scope;
if (args.Length() != 1 || !args[0]->IsInt32()) {
View
4 src/node_stat_watcher.cc
@@ -46,6 +46,10 @@ void StatWatcher::Callback(EV_P_ ev_stat *watcher, int revents) {
Handle<Value> StatWatcher::New(const Arguments& args) {
+ if (!args.IsConstructCall()) {
+ return FromConstructorTemplate(constructor_template, args);
+ }
+
HandleScope scope;
StatWatcher *s = new StatWatcher();
s->Wrap(args.Holder());
View
4 src/node_timer.cc
@@ -97,6 +97,10 @@ Timer::~Timer ()
Handle<Value>
Timer::New (const Arguments& args)
{
+ if (!args.IsConstructCall()) {
+ return FromConstructorTemplate(constructor_template, args);
+ }
+
HandleScope scope;
Timer *t = new Timer();
Please sign in to comment.
Something went wrong with that request. Please try again.