src: remove ObjectWrap dependency from core
authorBen Noordhuis <info@bnoordhuis.nl>
Wed, 25 Sep 2013 10:57:03 +0000 (12:57 +0200)
committerBen Noordhuis <info@bnoordhuis.nl>
Wed, 25 Sep 2013 17:44:53 +0000 (19:44 +0200)
Drop the ObjectWrap dependency in favor of an internal WeakObject class.

Let's us stop worrying about API and ABI compatibility when making
changes to the way node.js deals with weakly persistent handles
internally.

12 files changed:
node.gyp
src/node_contextify.cc
src/node_crypto.cc
src/node_crypto.h
src/node_http_parser.cc
src/node_stat_watcher.cc
src/node_stat_watcher.h
src/node_zlib.cc
src/tls_wrap.cc
src/tls_wrap.h
src/weak-object-inl.h [new file with mode: 0644]
src/weak-object.h [new file with mode: 0644]

index 3ff177a..7947a23 100644 (file)
--- a/node.gyp
+++ b/node.gyp
         'src/tree.h',
         'src/util.h',
         'src/util-inl.h',
+        'src/weak-object.h',
+        'src/weak-object-inl.h',
         'deps/http_parser/http_parser.h',
         '<(SHARED_INTERMEDIATE_DIR)/node_natives.h',
         # javascript files to make for an even more pleasant IDE experience
index c76b99d..ca281df 100644 (file)
@@ -24,6 +24,8 @@
 #include "node_watchdog.h"
 #include "env.h"
 #include "env-inl.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
 
 namespace node {
 
@@ -304,7 +306,7 @@ class ContextifyContext {
   }
 };
 
-class ContextifyScript : public ObjectWrap {
+class ContextifyScript : public WeakObject {
  private:
   Persistent<Script> script_;
 
@@ -335,8 +337,8 @@ class ContextifyScript : public ObjectWrap {
       return ThrowError("Must call vm.Script as a constructor.");
     }
 
-    ContextifyScript *contextify_script = new ContextifyScript();
-    contextify_script->Wrap(args.Holder());
+    ContextifyScript* contextify_script =
+        new ContextifyScript(args.GetIsolate(), args.This());
 
     TryCatch try_catch;
     Local<String> code = args[0]->ToString();
@@ -497,7 +499,7 @@ class ContextifyScript : public ObjectWrap {
     }
 
     ContextifyScript* wrapped_script =
-        ObjectWrap::Unwrap<ContextifyScript>(args.This());
+        WeakObject::Unwrap<ContextifyScript>(args.This());
     Local<Script> script = PersistentToLocal(node_isolate,
                                              wrapped_script->script_);
 
@@ -527,6 +529,11 @@ class ContextifyScript : public ObjectWrap {
   }
 
 
+  ContextifyScript(Isolate* isolate, Local<Object> object)
+      : WeakObject(isolate, object) {
+  }
+
+
   ~ContextifyScript() {
     script_.Dispose();
   }
index 6de073e..aa08fd8 100644 (file)
@@ -223,16 +223,14 @@ void SecureContext::Initialize(Environment* env, Handle<Object> target) {
 
 void SecureContext::New(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args.GetIsolate());
-  HandleScope handle_scope(args.GetIsolate());
-  SecureContext* sc = new SecureContext(env);
-  sc->Wrap(args.This());
+  new SecureContext(env, args.This());
 }
 
 
 void SecureContext::Init(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   OPENSSL_CONST SSL_METHOD *method = SSLv23_method();
 
@@ -356,7 +354,7 @@ static X509* LoadX509(Handle<Value> v) {
 void SecureContext::SetKey(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   unsigned int len = args.Length();
   if (len != 1 && len != 2) {
@@ -458,7 +456,7 @@ int SSL_CTX_use_certificate_chain(SSL_CTX *ctx, BIO *in) {
 void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() != 1) {
     return ThrowTypeError("Bad parameter");
@@ -485,7 +483,7 @@ void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
   bool newCAStore = false;
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() != 1) {
     return ThrowTypeError("Bad parameter");
@@ -513,7 +511,7 @@ void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
 void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() != 1) {
     return ThrowTypeError("Bad parameter");
@@ -544,7 +542,7 @@ void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
 void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   assert(sc->ca_store_ == NULL);
 
@@ -581,7 +579,7 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
 void SecureContext::SetCiphers(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() != 1 || !args[0]->IsString()) {
     return ThrowTypeError("Bad parameter");
@@ -595,7 +593,7 @@ void SecureContext::SetCiphers(const FunctionCallbackInfo<Value>& args) {
 void SecureContext::SetOptions(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() != 1 || !args[0]->IntegerValue()) {
     return ThrowTypeError("Bad parameter");
@@ -609,7 +607,7 @@ void SecureContext::SetSessionIdContext(
     const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() != 1 || !args[0]->IsString()) {
     return ThrowTypeError("Bad parameter");
@@ -645,7 +643,7 @@ void SecureContext::SetSessionIdContext(
 void SecureContext::SetSessionTimeout(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() != 1 || !args[0]->IsInt32()) {
     return ThrowTypeError("Bad parameter");
@@ -658,7 +656,7 @@ void SecureContext::SetSessionTimeout(const FunctionCallbackInfo<Value>& args) {
 
 void SecureContext::Close(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
   sc->FreeCTXMem();
 }
 
@@ -675,7 +673,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
   char* pass = NULL;
   bool ret = false;
 
-  SecureContext *sc = ObjectWrap::Unwrap<SecureContext>(args.This());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args.This());
 
   if (args.Length() < 1) {
     return ThrowTypeError("Bad parameter");
@@ -846,7 +844,7 @@ int SSLWrap<Base>::NewSessionCallback(SSL* s, SSL_SESSION* sess) {
                                       sess->session_id_length);
   Local<Value> argv[] = { session, buff };
   MakeCallback(env,
-               w->handle(node_isolate),
+               w->weak_object(node_isolate),
                env->onnewsession_string(),
                ARRAY_SIZE(argv),
                argv);
@@ -881,7 +879,7 @@ void SSLWrap<Base>::OnClientHello(void* arg,
 
   Local<Value> argv[] = { hello_obj };
   MakeCallback(env,
-               w->handle(node_isolate),
+               w->weak_object(node_isolate),
                env->onclienthello_string(),
                ARRAY_SIZE(argv),
                argv);
@@ -1423,7 +1421,7 @@ int Connection::HandleBIOError(BIO *bio, const char* func, int rv) {
     HandleScope scope(node_isolate);
     Local<Value> exception =
         Exception::Error(OneByteString(node_isolate, ssl_error_buf));
-    handle(node_isolate)->Set(
+    weak_object(node_isolate)->Set(
         FIXED_ONE_BYTE_STRING(node_isolate, "error"), exception);
 
     DEBUG_PRINT("[%p] BIO: %s failed: (%d) %s\n",
@@ -1467,7 +1465,7 @@ int Connection::HandleSSLError(const char* func,
   } else if (err == SSL_ERROR_ZERO_RETURN) {
     Local<Value> exception =
         Exception::Error(FIXED_ONE_BYTE_STRING(node_isolate, "ZERO_RETURN"));
-    handle(node_isolate)->Set(
+    weak_object(node_isolate)->Set(
         FIXED_ONE_BYTE_STRING(node_isolate, "error"), exception);
     return rv;
 
@@ -1492,7 +1490,7 @@ int Connection::HandleSSLError(const char* func,
       BIO_get_mem_ptr(bio, &mem);
       Local<Value> exception =
           Exception::Error(OneByteString(node_isolate, mem->data, mem->length));
-      handle(node_isolate)->Set(
+      weak_object(node_isolate)->Set(
           FIXED_ONE_BYTE_STRING(node_isolate, "error"), exception);
       BIO_free_all(bio);
     }
@@ -1510,7 +1508,7 @@ void Connection::ClearError() {
 
   // We should clear the error in JS-land
   Local<String> error_key = FIXED_ONE_BYTE_STRING(node_isolate, "error");
-  Local<Value> error = handle(node_isolate)->Get(error_key);
+  Local<Value> error = weak_object(node_isolate)->Get(error_key);
   assert(error->BooleanValue() == false);
 #endif  // NDEBUG
 }
@@ -1524,13 +1522,13 @@ void Connection::SetShutdownFlags() {
   if (flags & SSL_SENT_SHUTDOWN) {
     Local<String> sent_shutdown_key =
         FIXED_ONE_BYTE_STRING(node_isolate, "sentShutdown");
-    handle(node_isolate)->Set(sent_shutdown_key, True(node_isolate));
+    weak_object(node_isolate)->Set(sent_shutdown_key, True(node_isolate));
   }
 
   if (flags & SSL_RECEIVED_SHUTDOWN) {
     Local<String> received_shutdown_key =
         FIXED_ONE_BYTE_STRING(node_isolate, "receivedShutdown");
-    handle(node_isolate)->Set(received_shutdown_key, True(node_isolate));
+    weak_object(node_isolate)->Set(received_shutdown_key, True(node_isolate));
   }
 }
 
@@ -1645,7 +1643,7 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) {
           env->secure_context_constructor_template();
       if (secure_context_constructor_template->HasInstance(ret)) {
         conn->sniContext_.Reset(node_isolate, ret);
-        SecureContext* sc = ObjectWrap::Unwrap<SecureContext>(ret.As<Object>());
+        SecureContext* sc = WeakObject::Unwrap<SecureContext>(ret.As<Object>());
         SSL_set_SSL_CTX(s, sc->ctx_);
       } else {
         return SSL_TLSEXT_ERR_NOACK;
@@ -1664,16 +1662,14 @@ void Connection::New(const FunctionCallbackInfo<Value>& args) {
     return ThrowError("First argument must be a crypto module Credentials");
   }
 
-  SecureContext* sc = ObjectWrap::Unwrap<SecureContext>(args[0]->ToObject());
+  SecureContext* sc = WeakObject::Unwrap<SecureContext>(args[0]->ToObject());
   Environment* env = sc->env();
 
   bool is_server = args[1]->BooleanValue();
 
   SSLWrap<Connection>::Kind kind =
       is_server ? SSLWrap<Connection>::kServer : SSLWrap<Connection>::kClient;
-  Connection* conn = new Connection(env, sc, kind);
-  conn->Wrap(args.This());
-
+  Connection* conn = new Connection(env, args.This(), sc, kind);
   conn->ssl_ = SSL_new(sc->ctx_);
   conn->bio_read_ = NodeBIO::New();
   conn->bio_write_ = NodeBIO::New();
@@ -1759,13 +1755,13 @@ void Connection::SSLInfoCallback(const SSL *ssl_, int where, int ret) {
 
   if (where & SSL_CB_HANDSHAKE_START) {
     MakeCallback(env,
-                 conn->handle(node_isolate),
+                 conn->weak_object(node_isolate),
                  env->onhandshakestart_string());
   }
 
   if (where & SSL_CB_HANDSHAKE_DONE) {
     MakeCallback(env,
-                 conn->handle(node_isolate),
+                 conn->weak_object(node_isolate),
                  env->onhandshakedone_string());
   }
 }
@@ -2079,9 +2075,8 @@ void CipherBase::Initialize(Environment* env, Handle<Object> target) {
 
 void CipherBase::New(const FunctionCallbackInfo<Value>& args) {
   assert(args.IsConstructCall() == true);
-  HandleScope scope(node_isolate);
-  CipherBase* cipher = new CipherBase(args[0]->IsTrue() ? kCipher : kDecipher);
-  cipher->Wrap(args.This());
+  CipherKind kind = args[0]->IsTrue() ? kCipher : kDecipher;
+  new CipherBase(args.GetIsolate(), args.This(), kind);
 }
 
 
@@ -2128,7 +2123,7 @@ void CipherBase::Init(const char* cipher_type,
 void CipherBase::Init(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
+  CipherBase* cipher = WeakObject::Unwrap<CipherBase>(args.This());
 
   if (args.Length() < 2 ||
       !(args[0]->IsString() && Buffer::HasInstance(args[1]))) {
@@ -2180,7 +2175,7 @@ void CipherBase::InitIv(const char* cipher_type,
 void CipherBase::InitIv(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
+  CipherBase* cipher = WeakObject::Unwrap<CipherBase>(args.This());
 
   if (args.Length() < 3 || !args[0]->IsString()) {
     return ThrowError("Must give cipher-type, key, and iv as argument");
@@ -2217,7 +2212,7 @@ void CipherBase::Update(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args.GetIsolate());
   HandleScope handle_scope(args.GetIsolate());
 
-  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
+  CipherBase* cipher = WeakObject::Unwrap<CipherBase>(args.This());
 
   ASSERT_IS_STRING_OR_BUFFER(args[0]);
 
@@ -2262,7 +2257,7 @@ bool CipherBase::SetAutoPadding(bool auto_padding) {
 
 void CipherBase::SetAutoPadding(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
-  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
+  CipherBase* cipher = WeakObject::Unwrap<CipherBase>(args.This());
   cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue());
 }
 
@@ -2283,7 +2278,7 @@ void CipherBase::Final(const FunctionCallbackInfo<Value>& args) {
   Environment* env = Environment::GetCurrent(args.GetIsolate());
   HandleScope handle_scope(args.GetIsolate());
 
-  CipherBase* cipher = ObjectWrap::Unwrap<CipherBase>(args.This());
+  CipherBase* cipher = WeakObject::Unwrap<CipherBase>(args.This());
 
   unsigned char* out_value = NULL;
   int out_len = -1;
@@ -2317,9 +2312,7 @@ void Hmac::Initialize(Environment* env, v8::Handle<v8::Object> target) {
 
 
 void Hmac::New(const FunctionCallbackInfo<Value>& args) {
-  HandleScope scope(node_isolate);
-  Hmac* hmac = new Hmac();
-  hmac->Wrap(args.This());
+  new Hmac(args.GetIsolate(), args.This());
 }
 
 
@@ -2344,7 +2337,7 @@ void Hmac::HmacInit(const char* hash_type, const char* key, int key_len) {
 void Hmac::HmacInit(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
+  Hmac* hmac = WeakObject::Unwrap<Hmac>(args.This());
 
   if (args.Length() < 2 || !args[0]->IsString()) {
     return ThrowError("Must give hashtype string, key as arguments");
@@ -2369,7 +2362,7 @@ bool Hmac::HmacUpdate(const char* data, int len) {
 void Hmac::HmacUpdate(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
+  Hmac* hmac = WeakObject::Unwrap<Hmac>(args.This());
 
   ASSERT_IS_STRING_OR_BUFFER(args[0]);
 
@@ -2410,7 +2403,7 @@ bool Hmac::HmacDigest(unsigned char** md_value, unsigned int* md_len) {
 void Hmac::HmacDigest(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Hmac* hmac = ObjectWrap::Unwrap<Hmac>(args.This());
+  Hmac* hmac = WeakObject::Unwrap<Hmac>(args.This());
 
   enum encoding encoding = BUFFER;
   if (args.Length() >= 1) {
@@ -2454,13 +2447,10 @@ void Hash::New(const FunctionCallbackInfo<Value>& args) {
 
   const String::Utf8Value hash_type(args[0]);
 
-  Hash* hash = new Hash();
+  Hash* hash = new Hash(args.GetIsolate(), args.This());
   if (!hash->HashInit(*hash_type)) {
-    delete hash;
     return ThrowError("Digest method not supported");
   }
-
-  hash->Wrap(args.This());
 }
 
 
@@ -2485,7 +2475,7 @@ bool Hash::HashUpdate(const char* data, int len) {
 void Hash::HashUpdate(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Hash* hash = ObjectWrap::Unwrap<Hash>(args.This());
+  Hash* hash = WeakObject::Unwrap<Hash>(args.This());
 
   ASSERT_IS_STRING_OR_BUFFER(args[0]);
 
@@ -2516,7 +2506,7 @@ void Hash::HashUpdate(const FunctionCallbackInfo<Value>& args) {
 void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Hash* hash = ObjectWrap::Unwrap<Hash>(args.This());
+  Hash* hash = WeakObject::Unwrap<Hash>(args.This());
 
   if (!hash->initialised_) {
     return ThrowError("Not initialized");
@@ -2554,9 +2544,7 @@ void Sign::Initialize(Environment* env, v8::Handle<v8::Object> target) {
 
 
 void Sign::New(const FunctionCallbackInfo<Value>& args) {
-  HandleScope scope(node_isolate);
-  Sign* sign = new Sign();
-  sign->Wrap(args.This());
+  new Sign(args.GetIsolate(), args.This());
 }
 
 
@@ -2577,7 +2565,7 @@ void Sign::SignInit(const char* sign_type) {
 void Sign::SignInit(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
+  Sign* sign = WeakObject::Unwrap<Sign>(args.This());
 
   if (args.Length() == 0 || !args[0]->IsString()) {
     return ThrowError("Must give signtype string as argument");
@@ -2598,7 +2586,7 @@ bool Sign::SignUpdate(const char* data, int len) {
 void Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
+  Sign* sign = WeakObject::Unwrap<Sign>(args.This());
 
   ASSERT_IS_STRING_OR_BUFFER(args[0]);
 
@@ -2652,7 +2640,7 @@ bool Sign::SignFinal(unsigned char** md_value,
 void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Sign* sign = ObjectWrap::Unwrap<Sign>(args.This());
+  Sign* sign = WeakObject::Unwrap<Sign>(args.This());
 
   unsigned char* md_value;
   unsigned int md_len;
@@ -2697,9 +2685,7 @@ void Verify::Initialize(Environment* env, v8::Handle<v8::Object> target) {
 
 
 void Verify::New(const FunctionCallbackInfo<Value>& args) {
-  HandleScope scope(node_isolate);
-  Verify* verify = new Verify();
-  verify->Wrap(args.This());
+  new Verify(args.GetIsolate(), args.This());
 }
 
 
@@ -2721,7 +2707,7 @@ void Verify::VerifyInit(const char* verify_type) {
 void Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
+  Verify* verify = WeakObject::Unwrap<Verify>(args.This());
 
   if (args.Length() == 0 || !args[0]->IsString()) {
     return ThrowError("Must give verifytype string as argument");
@@ -2742,7 +2728,7 @@ bool Verify::VerifyUpdate(const char* data, int len) {
 void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
+  Verify* verify = WeakObject::Unwrap<Verify>(args.This());
 
   ASSERT_IS_STRING_OR_BUFFER(args[0]);
 
@@ -2851,7 +2837,7 @@ bool Verify::VerifyFinal(const char* key_pem,
 void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  Verify* verify = ObjectWrap::Unwrap<Verify>(args.This());
+  Verify* verify = WeakObject::Unwrap<Verify>(args.This());
 
   ASSERT_IS_BUFFER(args[0]);
   char* kbuf = Buffer::Data(args[0]);
@@ -2951,7 +2937,8 @@ void DiffieHellman::DiffieHellmanGroup(
     const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  DiffieHellman* diffieHellman = new DiffieHellman();
+  DiffieHellman* diffieHellman =
+      new DiffieHellman(args.GetIsolate(), args.This());
 
   if (args.Length() != 1 || !args[0]->IsString()) {
     return ThrowError("No group name given");
@@ -2968,7 +2955,6 @@ void DiffieHellman::DiffieHellmanGroup(
                         it->prime_size,
                         it->gen,
                         it->gen_size);
-    diffieHellman->Wrap(args.This());
     return;
   }
 
@@ -2979,7 +2965,8 @@ void DiffieHellman::DiffieHellmanGroup(
 void DiffieHellman::New(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
-  DiffieHellman* diffieHellman = new DiffieHellman();
+  DiffieHellman* diffieHellman =
+      new DiffieHellman(args.GetIsolate(), args.This());
   bool initialized = false;
 
   if (args.Length() > 0) {
@@ -2994,8 +2981,6 @@ void DiffieHellman::New(const FunctionCallbackInfo<Value>& args) {
   if (!initialized) {
     return ThrowError("Initialization failed");
   }
-
-  diffieHellman->Wrap(args.This());
 }
 
 
@@ -3003,7 +2988,7 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
@@ -3027,7 +3012,7 @@ void DiffieHellman::GetPrime(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
@@ -3046,7 +3031,7 @@ void DiffieHellman::GetGenerator(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
@@ -3065,7 +3050,7 @@ void DiffieHellman::GetPublicKey(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
@@ -3089,7 +3074,7 @@ void DiffieHellman::GetPrivateKey(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
@@ -3113,7 +3098,7 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
@@ -3185,7 +3170,7 @@ void DiffieHellman::SetPublicKey(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
@@ -3206,7 +3191,7 @@ void DiffieHellman::SetPrivateKey(const FunctionCallbackInfo<Value>& args) {
   HandleScope scope(node_isolate);
 
   DiffieHellman* diffieHellman =
-      ObjectWrap::Unwrap<DiffieHellman>(args.This());
+      WeakObject::Unwrap<DiffieHellman>(args.This());
 
   if (!diffieHellman->initialised_) {
     return ThrowError("Not initialized");
index b6eb882..9d8ade3 100644 (file)
@@ -32,6 +32,9 @@
 #endif
 
 #include "env.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
+
 #include "v8.h"
 
 #include <openssl/ssl.h>
@@ -57,7 +60,7 @@ extern X509_STORE* root_cert_store;
 // Forward declaration
 class Connection;
 
-class SecureContext : public ObjectWrap {
+class SecureContext : public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -90,8 +93,8 @@ class SecureContext : public ObjectWrap {
   static void GetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void SetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  explicit SecureContext(Environment* env)
-      : ObjectWrap()
+  SecureContext(Environment* env, v8::Local<v8::Object> wrap)
+      : WeakObject(env->isolate(), wrap)
       , ca_store_(NULL)
       , ctx_(NULL)
       , env_(env) {
@@ -219,7 +222,7 @@ class SSLWrap {
   friend class SecureContext;
 };
 
-class Connection : public SSLWrap<Connection>, public ObjectWrap {
+class Connection : public SSLWrap<Connection>, public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -273,15 +276,17 @@ class Connection : public SSLWrap<Connection>, public ObjectWrap {
   void SetShutdownFlags();
 
   static Connection* Unwrap(v8::Local<v8::Object> object) {
-    Connection* conn = ObjectWrap::Unwrap<Connection>(object);
+    Connection* conn = WeakObject::Unwrap<Connection>(object);
     conn->ClearError();
     return conn;
   }
 
   Connection(Environment* env,
+             v8::Local<v8::Object> wrap,
              SecureContext* sc,
              SSLWrap<Connection>::Kind kind)
       : SSLWrap<Connection>(env, sc, kind)
+      , WeakObject(env->isolate(), wrap)
       , bio_read_(NULL)
       , bio_write_(NULL)
       , hello_offset_(0) {
@@ -312,7 +317,7 @@ class Connection : public SSLWrap<Connection>, public ObjectWrap {
   friend class SecureContext;
 };
 
-class CipherBase : public ObjectWrap {
+class CipherBase : public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -339,9 +344,13 @@ class CipherBase : public ObjectWrap {
   static void Final(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void SetAutoPadding(const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  explicit CipherBase(CipherKind kind) : cipher_(NULL),
-                                         initialised_(false),
-                                         kind_(kind) {
+  CipherBase(v8::Isolate* isolate,
+             v8::Local<v8::Object> wrap,
+             CipherKind kind)
+      : WeakObject(isolate, wrap)
+      , cipher_(NULL)
+      , initialised_(false)
+      , kind_(kind) {
   }
 
   ~CipherBase() {
@@ -356,7 +365,7 @@ class CipherBase : public ObjectWrap {
   CipherKind kind_;
 };
 
-class Hmac : public ObjectWrap {
+class Hmac : public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -370,7 +379,10 @@ class Hmac : public ObjectWrap {
   static void HmacUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void HmacDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  Hmac() : md_(NULL), initialised_(false) {
+  Hmac(v8::Isolate* isolate, v8::Local<v8::Object> wrap)
+      : WeakObject(isolate, wrap)
+      , md_(NULL)
+      , initialised_(false) {
   }
 
   ~Hmac() {
@@ -384,7 +396,7 @@ class Hmac : public ObjectWrap {
   bool initialised_;
 };
 
-class Hash : public ObjectWrap {
+class Hash : public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -396,7 +408,10 @@ class Hash : public ObjectWrap {
   static void HashUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void HashDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  Hash() : md_(NULL), initialised_(false) {
+  Hash(v8::Isolate* isolate, v8::Local<v8::Object> wrap)
+      : WeakObject(isolate, wrap)
+      , md_(NULL)
+      , initialised_(false) {
   }
 
   ~Hash() {
@@ -410,7 +425,7 @@ class Hash : public ObjectWrap {
   bool initialised_;
 };
 
-class Sign : public ObjectWrap {
+class Sign : public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -427,7 +442,10 @@ class Sign : public ObjectWrap {
   static void SignUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void SignFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  Sign() : md_(NULL), initialised_(false) {
+  Sign(v8::Isolate* isolate, v8::Local<v8::Object> wrap)
+      : WeakObject(isolate, wrap)
+      , md_(NULL)
+      , initialised_(false) {
   }
 
   ~Sign() {
@@ -441,7 +459,7 @@ class Sign : public ObjectWrap {
   bool initialised_;
 };
 
-class Verify : public ObjectWrap {
+class Verify : public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -458,7 +476,10 @@ class Verify : public ObjectWrap {
   static void VerifyUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void VerifyFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  Verify() : md_(NULL), initialised_(false) {
+  Verify(v8::Isolate* isolate, v8::Local<v8::Object> wrap)
+      : WeakObject(isolate, wrap)
+      , md_(NULL)
+      , initialised_(false) {
   }
 
   ~Verify() {
@@ -472,7 +493,7 @@ class Verify : public ObjectWrap {
   bool initialised_;
 };
 
-class DiffieHellman : public ObjectWrap {
+class DiffieHellman : public WeakObject {
  public:
   static void Initialize(Environment* env, v8::Handle<v8::Object> target);
 
@@ -493,7 +514,10 @@ class DiffieHellman : public ObjectWrap {
   static void SetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void SetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
 
-  DiffieHellman() : ObjectWrap(), initialised_(false), dh(NULL) {
+  DiffieHellman(v8::Isolate* isolate, v8::Local<v8::Object> wrap)
+      : WeakObject(isolate, wrap)
+      , initialised_(false)
+      , dh(NULL) {
   }
 
   ~DiffieHellman() {
index 80046a9..8118091 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "env.h"
 #include "env-inl.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
 #include "v8.h"
 
 #include <stdlib.h>  // free()
@@ -185,10 +187,10 @@ struct StringPtr {
 };
 
 
-class Parser : public ObjectWrap {
+class Parser : public WeakObject {
  public:
-  Parser(Environment* env, enum http_parser_type type)
-      : ObjectWrap()
+  Parser(Environment* env, Local<Object> wrap, enum http_parser_type type)
+      : WeakObject(env->isolate(), wrap)
       , env_(env)
       , current_buffer_len_(0)
       , current_buffer_data_(NULL) {
@@ -252,7 +254,7 @@ class Parser : public ObjectWrap {
 
 
   HTTP_CB(on_headers_complete) {
-    Local<Object> obj = handle(node_isolate);
+    Local<Object> obj = weak_object(node_isolate);
     Local<Value> cb = obj->Get(kOnHeadersComplete);
 
     if (!cb->IsFunction())
@@ -313,7 +315,7 @@ class Parser : public ObjectWrap {
   HTTP_DATA_CB(on_body) {
     HandleScope scope(node_isolate);
 
-    Local<Object> obj = handle(node_isolate);
+    Local<Object> obj = weak_object(node_isolate);
     Local<Value> cb = obj->Get(kOnBody);
 
     if (!cb->IsFunction())
@@ -342,7 +344,7 @@ class Parser : public ObjectWrap {
     if (num_fields_)
       Flush();  // Flush trailing HTTP headers.
 
-    Local<Object> obj = handle(node_isolate);
+    Local<Object> obj = weak_object(node_isolate);
     Local<Value> cb = obj->Get(kOnMessageComplete);
 
     if (!cb->IsFunction())
@@ -362,13 +364,10 @@ class Parser : public ObjectWrap {
   static void New(const FunctionCallbackInfo<Value>& args) {
     Environment* env = Environment::GetCurrent(args.GetIsolate());
     HandleScope handle_scope(args.GetIsolate());
-
     http_parser_type type =
         static_cast<http_parser_type>(args[0]->Int32Value());
-
     assert(type == HTTP_REQUEST || type == HTTP_RESPONSE);
-    Parser* parser = new Parser(env, type);
-    parser->Wrap(args.This());
+    new Parser(env, args.This(), type);
   }
 
 
@@ -389,7 +388,7 @@ class Parser : public ObjectWrap {
   static void Execute(const FunctionCallbackInfo<Value>& args) {
     HandleScope scope(node_isolate);
 
-    Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
+    Parser* parser = WeakObject::Unwrap<Parser>(args.This());
     assert(parser->current_buffer_.IsEmpty());
     assert(parser->current_buffer_len_ == 0);
     assert(parser->current_buffer_data_ == NULL);
@@ -443,7 +442,7 @@ class Parser : public ObjectWrap {
   static void Finish(const FunctionCallbackInfo<Value>& args) {
     HandleScope scope(node_isolate);
 
-    Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
+    Parser* parser = WeakObject::Unwrap<Parser>(args.This());
 
     assert(parser->current_buffer_.IsEmpty());
     parser->got_exception_ = false;
@@ -476,7 +475,7 @@ class Parser : public ObjectWrap {
         static_cast<http_parser_type>(args[0]->Int32Value());
 
     assert(type == HTTP_REQUEST || type == HTTP_RESPONSE);
-    Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
+    Parser* parser = WeakObject::Unwrap<Parser>(args.This());
     // Should always be called from the same context.
     assert(env == parser->env());
     parser->Init(type);
@@ -503,7 +502,7 @@ class Parser : public ObjectWrap {
   void Flush() {
     HandleScope scope(node_isolate);
 
-    Local<Object> obj = handle(node_isolate);
+    Local<Object> obj = weak_object(node_isolate);
     Local<Value> cb = obj->Get(kOnHeaders);
 
     if (!cb->IsFunction())
index 1cd13c0..892ccac 100644 (file)
@@ -22,6 +22,8 @@
 #include "node_stat_watcher.h"
 #include "env.h"
 #include "env-inl.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
 
 #include <assert.h>
 #include <string.h>
@@ -61,8 +63,8 @@ static void Delete(uv_handle_t* handle) {
 }
 
 
-StatWatcher::StatWatcher(Environment* env)
-    : ObjectWrap()
+StatWatcher::StatWatcher(Environment* env, Local<Object> wrap)
+    : WeakObject(env->isolate(), wrap)
     , watcher_(new uv_fs_poll_t)
     , env_(env) {
   uv_fs_poll_init(env->event_loop(), watcher_);
@@ -91,7 +93,7 @@ void StatWatcher::Callback(uv_fs_poll_t* handle,
     Integer::New(status, node_isolate)
   };
   MakeCallback(env,
-               wrap->handle(node_isolate),
+               wrap->weak_object(node_isolate),
                env->onchange_string(),
                ARRAY_SIZE(argv),
                argv);
@@ -102,8 +104,7 @@ void StatWatcher::New(const FunctionCallbackInfo<Value>& args) {
   assert(args.IsConstructCall());
   Environment* env = Environment::GetCurrent(args.GetIsolate());
   HandleScope handle_scope(args.GetIsolate());
-  StatWatcher* s = new StatWatcher(env);
-  s->Wrap(args.This());
+  new StatWatcher(env, args.This());
 }
 
 
@@ -111,23 +112,23 @@ void StatWatcher::Start(const FunctionCallbackInfo<Value>& args) {
   assert(args.Length() == 3);
   HandleScope scope(node_isolate);
 
-  StatWatcher* wrap = ObjectWrap::Unwrap<StatWatcher>(args.This());
+  StatWatcher* wrap = WeakObject::Unwrap<StatWatcher>(args.This());
   String::Utf8Value path(args[0]);
   const bool persistent = args[1]->BooleanValue();
   const uint32_t interval = args[2]->Uint32Value();
 
   if (!persistent) uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
   uv_fs_poll_start(wrap->watcher_, Callback, *path, interval);
-  wrap->Ref();
+  wrap->ClearWeak();
 }
 
 
 void StatWatcher::Stop(const FunctionCallbackInfo<Value>& args) {
-  StatWatcher* wrap = ObjectWrap::Unwrap<StatWatcher>(args.This());
+  StatWatcher* wrap = WeakObject::Unwrap<StatWatcher>(args.This());
   Environment* env = wrap->env();
   Context::Scope context_scope(env->context());
   HandleScope handle_scope(env->isolate());
-  MakeCallback(env, wrap->handle(node_isolate), env->onstop_string());
+  MakeCallback(env, wrap->weak_object(node_isolate), env->onstop_string());
   wrap->Stop();
 }
 
@@ -135,7 +136,7 @@ void StatWatcher::Stop(const FunctionCallbackInfo<Value>& args) {
 void StatWatcher::Stop() {
   if (!uv_is_active(reinterpret_cast<uv_handle_t*>(watcher_))) return;
   uv_fs_poll_stop(watcher_);
-  Unref();
+  MakeWeak();
 }
 
 
index 9d5e1fd..eb6b9d2 100644 (file)
 #include "env.h"
 #include "uv.h"
 #include "v8.h"
+#include "weak-object.h"
 
 namespace node {
 
-class StatWatcher : public ObjectWrap {
+class StatWatcher : public WeakObject {
  public:
   static void Initialize(v8::Handle<v8::Object> target);
   inline Environment* env() const { return env_; }
 
  protected:
-  explicit StatWatcher(Environment* env);
+  StatWatcher(Environment* env, v8::Local<v8::Object> wrap);
   virtual ~StatWatcher();
 
   static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
index ebc9d2b..de5f1d5 100644 (file)
@@ -24,6 +24,9 @@
 
 #include "env.h"
 #include "env-inl.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
+
 #include "v8.h"
 #include "zlib.h"
 
@@ -64,11 +67,11 @@ void InitZlib(v8::Handle<v8::Object> target);
 /**
  * Deflate/Inflate
  */
-class ZCtx : public ObjectWrap {
+class ZCtx : public WeakObject {
  public:
 
-  ZCtx(Environment* env, node_zlib_mode mode)
-      : ObjectWrap()
+  ZCtx(Environment* env, Local<Object> wrap, node_zlib_mode mode)
+      : WeakObject(env->isolate(), wrap)
       , chunk_size_(0)
       , dictionary_(NULL)
       , dictionary_len_(0)
@@ -118,7 +121,7 @@ class ZCtx : public ObjectWrap {
 
   static void Close(const FunctionCallbackInfo<Value>& args) {
     HandleScope scope(node_isolate);
-    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
+    ZCtx* ctx = WeakObject::Unwrap<ZCtx>(args.This());
     ctx->Close();
   }
 
@@ -128,13 +131,13 @@ class ZCtx : public ObjectWrap {
     HandleScope scope(node_isolate);
     assert(args.Length() == 7);
 
-    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
+    ZCtx* ctx = WeakObject::Unwrap<ZCtx>(args.This());
     assert(ctx->init_done_ && "write before init");
     assert(ctx->mode_ != NONE && "already finalized");
 
     assert(!ctx->write_in_progress_ && "write already in progress");
     ctx->write_in_progress_ = true;
-    ctx->Ref();
+    ctx->ClearWeak();
 
     assert(!args[0]->IsUndefined() && "must provide flush value");
 
@@ -194,7 +197,7 @@ class ZCtx : public ObjectWrap {
                   ZCtx::Process,
                   ZCtx::After);
 
-    args.GetReturnValue().Set(ctx->persistent());
+    args.GetReturnValue().Set(ctx->weak_object(node_isolate));
   }
 
 
@@ -284,11 +287,11 @@ class ZCtx : public ObjectWrap {
     ctx->write_in_progress_ = false;
 
     // call the write() cb
-    Local<Object> handle = ctx->handle(node_isolate);
+    Local<Object> handle = ctx->weak_object(node_isolate);
     Local<Value> args[2] = { avail_in, avail_out };
     MakeCallback(env, handle, env->callback_string(), ARRAY_SIZE(args), args);
 
-    ctx->Unref();
+    ctx->MakeWeak();
   }
 
   static void Error(ZCtx* ctx, const char* message) {
@@ -301,7 +304,7 @@ class ZCtx : public ObjectWrap {
       message = ctx->strm_.msg;
     }
 
-    Local<Object> handle = ctx->handle(node_isolate);
+    Local<Object> handle = ctx->weak_object(node_isolate);
     HandleScope scope(node_isolate);
     Local<Value> args[2] = {
       OneByteString(node_isolate, message),
@@ -311,7 +314,7 @@ class ZCtx : public ObjectWrap {
 
     // no hope of rescue.
     ctx->write_in_progress_ = false;
-    ctx->Unref();
+    ctx->MakeWeak();
   }
 
   static void New(const FunctionCallbackInfo<Value>& args) {
@@ -327,8 +330,7 @@ class ZCtx : public ObjectWrap {
       return ThrowTypeError("Bad argument");
     }
 
-    ZCtx* ctx = new ZCtx(env, mode);
-    ctx->Wrap(args.This());
+    new ZCtx(env, args.This(), mode);
   }
 
   // just pull the ints out of the args and call the other Init
@@ -338,7 +340,7 @@ class ZCtx : public ObjectWrap {
     assert((args.Length() == 4 || args.Length() == 5) &&
            "init(windowBits, level, memLevel, strategy, [dictionary])");
 
-    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
+    ZCtx* ctx = WeakObject::Unwrap<ZCtx>(args.This());
 
     int windowBits = args[0]->Uint32Value();
     assert((windowBits >= 8 && windowBits <= 15) && "invalid windowBits");
@@ -377,7 +379,7 @@ class ZCtx : public ObjectWrap {
 
     assert(args.Length() == 2 && "params(level, strategy)");
 
-    ZCtx* ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
+    ZCtx* ctx = WeakObject::Unwrap<ZCtx>(args.This());
 
     Params(ctx, args[0]->Int32Value(), args[1]->Int32Value());
   }
@@ -385,7 +387,7 @@ class ZCtx : public ObjectWrap {
   static void Reset(const FunctionCallbackInfo<Value> &args) {
     HandleScope scope(node_isolate);
 
-    ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
+    ZCtx* ctx = WeakObject::Unwrap<ZCtx>(args.This());
 
     Reset(ctx);
     SetDictionary(ctx);
index e6afda6..a0eea75 100644 (file)
@@ -58,7 +58,7 @@ TLSCallbacks::TLSCallbacks(Environment* env,
                            Kind kind,
                            Handle<Object> sc,
                            StreamWrapCallbacks* old)
-    : SSLWrap<TLSCallbacks>(env, ObjectWrap::Unwrap<SecureContext>(sc), kind),
+    : SSLWrap<TLSCallbacks>(env, WeakObject::Unwrap<SecureContext>(sc), kind),
       StreamWrapCallbacks(old),
       enc_in_(NULL),
       enc_out_(NULL),
@@ -70,7 +70,7 @@ TLSCallbacks::TLSCallbacks(Environment* env,
       shutdown_(false) {
 
   // Persist SecureContext
-  sc_ = ObjectWrap::Unwrap<SecureContext>(sc);
+  sc_ = WeakObject::Unwrap<SecureContext>(sc);
   sc_handle_.Reset(node_isolate, sc);
 
   Local<Object> object = env->tls_wrap_constructor_function()->NewInstance();
@@ -236,7 +236,7 @@ void TLSCallbacks::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
   // There should be a Context::Scope a few stack frames down.
   assert(env->context() == env->isolate()->GetCurrentContext());
   HandleScope handle_scope(env->isolate());
-  Local<Object> object = c->object(env->isolate());
+  Local<Object> object = c->weak_object(env->isolate());
 
   if (where & SSL_CB_HANDSHAKE_START) {
     Local<Value> callback = object->Get(env->onhandshakestart_string());
@@ -313,7 +313,7 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
         FIXED_ONE_BYTE_STRING(node_isolate, "write cb error, status: "),
         Integer::New(status, node_isolate)->ToString());
     MakeCallback(env,
-                 callbacks->object(node_isolate),
+                 callbacks->weak_object(node_isolate),
                  env->onerror_string(),
                  1,
                  &arg);
@@ -398,7 +398,7 @@ void TLSCallbacks::ClearOut() {
 
     if (!argv.IsEmpty()) {
       MakeCallback(env(),
-                   object(node_isolate),
+                   weak_object(node_isolate),
                    env()->onerror_string(),
                    1,
                    &argv);
@@ -437,7 +437,7 @@ bool TLSCallbacks::ClearIn() {
   Handle<Value> argv = GetSSLError(written, &err);
   if (!argv.IsEmpty()) {
     MakeCallback(env(),
-                 object(node_isolate),
+                 weak_object(node_isolate),
                  env()->onerror_string(),
                  1,
                  &argv);
@@ -504,7 +504,7 @@ int TLSCallbacks::DoWrite(WriteWrap* w,
     Handle<Value> argv = GetSSLError(written, &err);
     if (!argv.IsEmpty()) {
       MakeCallback(env(),
-                   object(node_isolate),
+                   weak_object(node_isolate),
                    env()->onerror_string(),
                    1,
                    &argv);
@@ -688,7 +688,7 @@ int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
 
   if (servername != NULL) {
     // Call the SNI callback and use its return value as context
-    Local<Object> object = p->object(node_isolate);
+    Local<Object> object = p->weak_object(node_isolate);
     Local<Value> ctx = object->Get(env->sni_context_string());
 
     if (!ctx->IsObject())
@@ -697,7 +697,7 @@ int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
     p->sni_context_.Dispose();
     p->sni_context_.Reset(node_isolate, ctx);
 
-    SecureContext* sc = ObjectWrap::Unwrap<SecureContext>(ctx.As<Object>());
+    SecureContext* sc = WeakObject::Unwrap<SecureContext>(ctx.As<Object>());
     SSL_set_SSL_CTX(s, sc->ctx_);
   }
 
index d8f3997..ec82154 100644 (file)
@@ -64,8 +64,8 @@ class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
   int DoShutdown(ShutdownWrap* req_wrap, uv_shutdown_cb cb);
 
   // Just for compliance with Connection
-  inline v8::Local<v8::Object> handle(v8::Isolate* isolate) {
-    return object(isolate);
+  inline v8::Local<v8::Object> weak_object(v8::Isolate* isolate) {
+    return PersistentToLocal(isolate, persistent());
   }
 
  protected:
@@ -123,10 +123,6 @@ class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
   static int SelectSNIContextCallback(SSL* s, int* ad, void* arg);
 #endif  // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
 
-  inline v8::Local<v8::Object> object(v8::Isolate* isolate) {
-    return PersistentToLocal(isolate, persistent());
-  }
-
   inline v8::Persistent<v8::Object>& persistent() {
     return object_;
   }
diff --git a/src/weak-object-inl.h b/src/weak-object-inl.h
new file mode 100644 (file)
index 0000000..0d293a4
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef SRC_WEAK_OBJECT_INL_H_
+#define SRC_WEAK_OBJECT_INL_H_
+
+#include "weak-object.h"
+
+namespace node {
+
+WeakObject::WeakObject(v8::Isolate* isolate, v8::Local<v8::Object> object)
+    : weak_object_(isolate, object) {
+  weak_object_.MarkIndependent();
+  object->SetAlignedPointerInInternalField(kInternalFieldIndex, this);
+  MakeWeak();
+}
+
+WeakObject::~WeakObject() {
+}
+
+v8::Local<v8::Object> WeakObject::weak_object(v8::Isolate* isolate) const {
+  return v8::Local<v8::Object>::New(isolate, weak_object_);
+}
+
+void WeakObject::MakeWeak() {
+  weak_object_.MakeWeak(this, WeakCallback);
+}
+
+void WeakObject::ClearWeak() {
+  weak_object_.ClearWeak();
+}
+
+template <typename TypeName>
+TypeName* WeakObject::Unwrap(v8::Local<v8::Object> object) {
+  // Cast to WeakObject* before casting to TypeName* avoids issues with classes
+  // that have multiple base classes.
+  void* p = object->GetAlignedPointerFromInternalField(kInternalFieldIndex);
+  WeakObject* w = static_cast<WeakObject*>(p);
+  return static_cast<TypeName*>(w);
+}
+
+void WeakObject::WeakCallback(v8::Isolate* isolate,
+                              v8::Persistent<v8::Object>* persistent,
+                              WeakObject* self) {
+  // Dispose now instead of in the destructor to avoid child classes that call
+  // `delete this` in their destructor from blowing up.
+  persistent->Dispose();
+  delete self;
+}
+
+}  // namespace node
+
+#endif  // SRC_WEAK_OBJECT_INL_H_
diff --git a/src/weak-object.h b/src/weak-object.h
new file mode 100644 (file)
index 0000000..b42332e
--- /dev/null
@@ -0,0 +1,54 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+#ifndef SRC_WEAK_OBJECT_H_
+#define SRC_WEAK_OBJECT_H_
+
+#include "v8.h"
+
+namespace node {
+
+class WeakObject {
+ public:
+  // FIXME(bnoordhuis) These methods are public only because the code base
+  // plays fast and loose with encapsulation.
+  template <typename TypeName>
+  inline static TypeName* Unwrap(v8::Local<v8::Object> object);
+  // Returns the wrapped object.  Illegal to call in your destructor.
+  inline v8::Local<v8::Object> weak_object(v8::Isolate* isolate) const;
+ protected:
+  // |object| should be an instance of a v8::ObjectTemplate that has at least
+  // one internal field reserved with v8::ObjectTemplate::SetInternalFieldCount.
+  inline WeakObject(v8::Isolate* isolate, v8::Local<v8::Object> object);
+  virtual inline ~WeakObject();
+  inline void MakeWeak();
+  inline void ClearWeak();
+ private:
+  inline static void WeakCallback(v8::Isolate* isolate,
+                                  v8::Persistent<v8::Object>* persistent,
+                                  WeakObject* self);
+  static const int kInternalFieldIndex = 0;
+  v8::Persistent<v8::Object> weak_object_;
+};
+
+}  // namespace node
+
+#endif  // SRC_WEAK_OBJECT_H_