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.
'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
#include "node_watchdog.h"
#include "env.h"
#include "env-inl.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
namespace node {
}
};
-class ContextifyScript : public ObjectWrap {
+class ContextifyScript : public WeakObject {
private:
Persistent<Script> script_;
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();
}
ContextifyScript* wrapped_script =
- ObjectWrap::Unwrap<ContextifyScript>(args.This());
+ WeakObject::Unwrap<ContextifyScript>(args.This());
Local<Script> script = PersistentToLocal(node_isolate,
wrapped_script->script_);
}
+ ContextifyScript(Isolate* isolate, Local<Object> object)
+ : WeakObject(isolate, object) {
+ }
+
+
~ContextifyScript() {
script_.Dispose();
}
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();
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) {
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");
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");
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");
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);
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");
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");
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");
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");
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();
}
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");
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);
Local<Value> argv[] = { hello_obj };
MakeCallback(env,
- w->handle(node_isolate),
+ w->weak_object(node_isolate),
env->onclienthello_string(),
ARRAY_SIZE(argv),
argv);
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",
} 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;
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);
}
// 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
}
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));
}
}
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;
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();
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());
}
}
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);
}
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]))) {
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");
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]);
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());
}
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;
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());
}
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");
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]);
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) {
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());
}
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]);
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");
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());
}
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");
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]);
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;
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());
}
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");
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]);
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]);
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");
it->prime_size,
it->gen,
it->gen_size);
- diffieHellman->Wrap(args.This());
return;
}
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) {
if (!initialized) {
return ThrowError("Initialization failed");
}
-
- diffieHellman->Wrap(args.This());
}
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
HandleScope scope(node_isolate);
DiffieHellman* diffieHellman =
- ObjectWrap::Unwrap<DiffieHellman>(args.This());
+ WeakObject::Unwrap<DiffieHellman>(args.This());
if (!diffieHellman->initialised_) {
return ThrowError("Not initialized");
#endif
#include "env.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
+
#include "v8.h"
#include <openssl/ssl.h>
// Forward declaration
class Connection;
-class SecureContext : public ObjectWrap {
+class SecureContext : public WeakObject {
public:
static void Initialize(Environment* env, v8::Handle<v8::Object> target);
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) {
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);
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) {
friend class SecureContext;
};
-class CipherBase : public ObjectWrap {
+class CipherBase : public WeakObject {
public:
static void Initialize(Environment* env, v8::Handle<v8::Object> target);
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() {
CipherKind kind_;
};
-class Hmac : public ObjectWrap {
+class Hmac : public WeakObject {
public:
static void Initialize(Environment* env, v8::Handle<v8::Object> target);
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() {
bool initialised_;
};
-class Hash : public ObjectWrap {
+class Hash : public WeakObject {
public:
static void Initialize(Environment* env, v8::Handle<v8::Object> target);
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() {
bool initialised_;
};
-class Sign : public ObjectWrap {
+class Sign : public WeakObject {
public:
static void Initialize(Environment* env, v8::Handle<v8::Object> target);
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() {
bool initialised_;
};
-class Verify : public ObjectWrap {
+class Verify : public WeakObject {
public:
static void Initialize(Environment* env, v8::Handle<v8::Object> target);
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() {
bool initialised_;
};
-class DiffieHellman : public ObjectWrap {
+class DiffieHellman : public WeakObject {
public:
static void Initialize(Environment* env, v8::Handle<v8::Object> target);
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() {
#include "env.h"
#include "env-inl.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
#include "v8.h"
#include <stdlib.h> // free()
};
-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) {
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())
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())
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())
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);
}
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);
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;
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);
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())
#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>
}
-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_);
Integer::New(status, node_isolate)
};
MakeCallback(env,
- wrap->handle(node_isolate),
+ wrap->weak_object(node_isolate),
env->onchange_string(),
ARRAY_SIZE(argv),
argv);
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());
}
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();
}
void StatWatcher::Stop() {
if (!uv_is_active(reinterpret_cast<uv_handle_t*>(watcher_))) return;
uv_fs_poll_stop(watcher_);
- Unref();
+ MakeWeak();
}
#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);
#include "env.h"
#include "env-inl.h"
+#include "weak-object.h"
+#include "weak-object-inl.h"
+
#include "v8.h"
#include "zlib.h"
/**
* 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)
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();
}
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");
ZCtx::Process,
ZCtx::After);
- args.GetReturnValue().Set(ctx->persistent());
+ args.GetReturnValue().Set(ctx->weak_object(node_isolate));
}
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) {
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),
// no hope of rescue.
ctx->write_in_progress_ = false;
- ctx->Unref();
+ ctx->MakeWeak();
}
static void New(const FunctionCallbackInfo<Value>& args) {
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
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");
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());
}
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);
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),
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();
// 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());
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);
if (!argv.IsEmpty()) {
MakeCallback(env(),
- object(node_isolate),
+ weak_object(node_isolate),
env()->onerror_string(),
1,
&argv);
Handle<Value> argv = GetSSLError(written, &err);
if (!argv.IsEmpty()) {
MakeCallback(env(),
- object(node_isolate),
+ weak_object(node_isolate),
env()->onerror_string(),
1,
&argv);
Handle<Value> argv = GetSSLError(written, &err);
if (!argv.IsEmpty()) {
MakeCallback(env(),
- object(node_isolate),
+ weak_object(node_isolate),
env()->onerror_string(),
1,
&argv);
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())
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_);
}
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:
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_;
}
--- /dev/null
+// 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_
--- /dev/null
+// 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_