Skip to content

Instantly share code, notes, and snippets.

@johnhaley81
Created April 20, 2015 18:04
Show Gist options
  • Save johnhaley81/938dcfa4975b9e92c085 to your computer and use it in GitHub Desktop.
Save johnhaley81/938dcfa4975b9e92c085 to your computer and use it in GitHub Desktop.
Trying out fixing cross thread calling in nodegit
// This is a generated file, modify: generate/templates/struct_content.cc.
#include <nan.h>
#include <string.h>
#include <chrono>
#include <thread>
extern "C" {
#include <git2.h>
}
#include <iostream>
#include "../include/functions/copy.h"
#include "../include/remote_callbacks.h"
#include "../include/cred.h"
#include "../include/cert.h"
#include "../include/transfer_progress.h"
using namespace v8;
using namespace node;
using namespace std;
// generated from struct_content.cc
GitRemoteCallbacks::GitRemoteCallbacks()
{
git_remote_callbacks wrappedValue = GIT_REMOTE_CALLBACKS_INIT;
this->raw = (git_remote_callbacks*) malloc(sizeof(git_remote_callbacks));
memcpy(this->raw, &wrappedValue, sizeof(git_remote_callbacks));
this->ConstructFields();
this->selfFreeing = true;
}
GitRemoteCallbacks::GitRemoteCallbacks(git_remote_callbacks* raw, bool selfFreeing)
{
this->raw = raw;
this->ConstructFields();
this->selfFreeing = selfFreeing;
}
GitRemoteCallbacks::~GitRemoteCallbacks()
{
if (this->credentials != NULL) {
delete this->credentials;
this->raw->payload = NULL;
}
if (this->certificate_check != NULL) {
delete this->certificate_check;
this->raw->payload = NULL;
}
if (this->transfer_progress != NULL) {
delete this->transfer_progress;
this->raw->payload = NULL;
}
if (this->selfFreeing) {
free(this->raw);
}
}
void GitRemoteCallbacks::ConstructFields()
{
// Set the static method call and set the payload for this function to be
// the current instance
this->raw->credentials = NULL;
this->raw->payload = (void *)this;
this->credentials = NULL;
// Set the static method call and set the payload for this function to be
// the current instance
this->raw->certificate_check = NULL;
this->raw->payload = (void *)this;
this->certificate_check = NULL;
// Set the static method call and set the payload for this function to be
// the current instance
this->raw->transfer_progress = NULL;
this->raw->payload = (void *)this;
this->transfer_progress = NULL;
Local<Value> payload = NanUndefined();
NanAssignPersistent(this->payload, payload);
}
void GitRemoteCallbacks::InitializeComponent(Handle<v8::Object> target)
{
NanScope();
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(JSNewFunction);
tpl->InstanceTemplate()->SetInternalFieldCount(1);
tpl->SetClassName(NanNew<String>("RemoteCallbacks"));
tpl->InstanceTemplate()->SetAccessor(NanNew<String>("version"), GetVersion, SetVersion);
tpl->InstanceTemplate()->SetAccessor(NanNew<String>("credentials"), GetCredentials, SetCredentials);
tpl->InstanceTemplate()->SetAccessor(NanNew<String>("certificateCheck"), GetCertificateCheck, SetCertificateCheck);
tpl->InstanceTemplate()->SetAccessor(NanNew<String>("transferProgress"), GetTransferProgress, SetTransferProgress);
Local<Function> _constructor_template = tpl->GetFunction();
NanAssignPersistent(constructor_template, _constructor_template);
target->Set(NanNew<String>("RemoteCallbacks"), _constructor_template);
}
NAN_METHOD(GitRemoteCallbacks::JSNewFunction)
{
NanScope();
GitRemoteCallbacks* instance;
if (args.Length() == 0 || !args[0]->IsExternal()) {
instance = new GitRemoteCallbacks();
} else {
instance = new GitRemoteCallbacks(static_cast<git_remote_callbacks*>(Handle<External>::Cast(args[0])->Value()), args[1]->BooleanValue());
}
instance->Wrap(args.This());
NanReturnValue(args.This());
}
Handle<v8::Value> GitRemoteCallbacks::New(void* raw, bool selfFreeing)
{
NanEscapableScope();
Handle<v8::Value> argv[2] = { NanNew<External>((void *)raw), NanNew<Boolean>(selfFreeing) };
return NanEscapeScope(NanNew<Function>(GitRemoteCallbacks::constructor_template)->NewInstance(2, argv));
}
git_remote_callbacks *GitRemoteCallbacks::GetValue()
{
return this->raw;
}
git_remote_callbacks **GitRemoteCallbacks::GetRefValue()
{
return this->raw == NULL ? NULL : &this->raw;
}
void GitRemoteCallbacks::ClearValue()
{
this->raw = NULL;
}
NAN_GETTER(GitRemoteCallbacks::GetVersion)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
NanReturnValue(NanNew<Number>(wrapper->GetValue()->version));
}
NAN_SETTER(GitRemoteCallbacks::SetVersion)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
if (value->IsNumber()) {
wrapper->GetValue()->version = (unsigned int) value->Int32Value();
}
}
NAN_GETTER(GitRemoteCallbacks::GetCredentials)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
NanReturnValue(wrapper->credentials->GetFunction());
}
NAN_SETTER(GitRemoteCallbacks::SetCredentials)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
if (wrapper->credentials != NULL) {
delete wrapper->credentials;
}
if (value->IsFunction()) {
if (!wrapper->raw->credentials) {
wrapper->raw->credentials = (git_cred_acquire_cb)credentials_cppCallback;
}
CredentialsBaton* baton = new CredentialsBaton();
baton->result = 0;
baton->req.data = baton;
baton->done = false;
baton->payload = wrapper;
uv_async_init(uv_default_loop(), &baton->req, (uv_async_cb) credentials_async);
wrapper->raw->payload = baton;
wrapper->credentials = new NanCallback(value.As<Function>());
}
NanReturnUndefined();
}
int GitRemoteCallbacks::credentials_cppCallback (
git_cred ** cred, const char * url, const char * username_from_url, unsigned int allowed_types, void * payload )
{
CredentialsBaton* baton = (CredentialsBaton*) payload;
baton->cred = cred;
baton->url = url;
baton->username_from_url = username_from_url;
baton->allowed_types = allowed_types;
uv_async_send(&baton->req);
while(!baton->done) {
this_thread::sleep_for(chrono::milliseconds(1));
}
*cred = *baton->cred;
return baton->result;
}
void GitRemoteCallbacks::credentials_async(uv_async_t* req, int status)
{
NanScope();
CredentialsBaton* baton = static_cast<CredentialsBaton*>(req->data);
GitRemoteCallbacks* instance = static_cast<GitRemoteCallbacks*>(baton->payload);
if (instance->credentials->IsEmpty()) {
baton->result = 1; // no results acquired
baton->done = true;
return;
}
if (baton->url == NULL) {
baton->url = "";
}
if (baton->username_from_url == NULL) {
baton->username_from_url = "";
}
if (baton->allowed_types == NULL) {
baton->allowed_types = 0;
}
Local<Value> argv[4] = {
NanNew(baton->url),
NanNew(baton->username_from_url),
NanNew(baton->allowed_types),
NanNew(instance->payload)
};
TryCatch tryCatch;
Handle<v8::Value> result = instance->credentials->Call(4, argv);
if (result->IsObject() && result->ToObject()->Has(NanNew("then"))) {
Handle<v8::Value> thenProp = result->ToObject()->Get(NanNew("then"));
if (thenProp->IsFunction()) {
// we can be reasonbly certain that the result is a promise
Local<Object> promise = result->ToObject();
NanAssignPersistent(baton->promise, promise);
uv_async_init(uv_default_loop(), &baton->req, (uv_async_cb) credentials_asyncPromisePolling);
uv_async_send(&baton->req);
return;
}
}
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = -1;
} else if (!result->IsNull() && !result->IsUndefined()) {
GitCred* wrapper = ObjectWrap::Unwrap<GitCred>(result->ToObject());
wrapper->selfFreeing = false;
baton->cred = wrapper->GetRefValue();
baton->result = 0;
} else {
baton->result = 1;
}
uv_close((uv_handle_t*) &baton->req, NULL);
baton->done = true;
NanReturnUndefined();
}
void GitRemoteCallbacks::credentials_asyncPromisePolling(uv_async_t* req, int status)
{
NanScope();
CredentialsBaton* baton = static_cast<CredentialsBaton*>(req->data);
Local<Object> promise = NanNew<Object>(baton->promise);
NanCallback* isPendingFn = new NanCallback(promise->Get(NanNew("isPending")).As<Function>());
Local<Value> argv[1]; // MSBUILD won't assign an array of length 0
Local<Boolean> isPending = isPendingFn->Call(0, argv)->ToBoolean();
if (isPending->Value()) {
uv_async_send(&baton->req);
return;
}
NanCallback* isFulfilledFn = new NanCallback(promise->Get(NanNew("isFulfilled")).As<Function>());
Local<Boolean> isFulfilled = isFulfilledFn->Call(0, argv)->ToBoolean();
if (isFulfilled->Value()) {
NanCallback* resultFn = new NanCallback(promise->Get(NanNew("value")).As<Function>());
Handle<v8::Value> result = resultFn->Call(0, argv);
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = -1;
} else if (!result->IsNull() && !result->IsUndefined()) {
GitCred* wrapper = ObjectWrap::Unwrap<GitCred>(result->ToObject());
wrapper->selfFreeing = false;
baton->cred = wrapper->GetRefValue();
baton->result = 0;
} else {
baton->result = 1;
}
} else {
// promise was rejected
baton->result = -1;
}
baton->done = true;
NanReturnUndefined();
}
NAN_GETTER(GitRemoteCallbacks::GetCertificateCheck)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
NanReturnValue(wrapper->certificate_check->GetFunction());
}
NAN_SETTER(GitRemoteCallbacks::SetCertificateCheck)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
if (wrapper->certificate_check != NULL) {
delete wrapper->certificate_check;
}
if (value->IsFunction()) {
if (!wrapper->raw->certificate_check) {
wrapper->raw->certificate_check = (git_transport_certificate_check_cb)certificate_check_cppCallback;
}
wrapper->certificate_check = new NanCallback(value.As<Function>());
}
NanReturnUndefined();
}
int GitRemoteCallbacks::certificate_check_cppCallback (
git_cert * cert, int valid, const char * host, void * payload )
{
CertificateCheckBaton* baton = new CertificateCheckBaton();
baton->cert = cert;
baton->valid = valid;
baton->host = host;
baton->payload = payload;
baton->result = 0;
baton->req.data = baton;
baton->done = false;
uv_async_init(uv_default_loop(), &baton->req, (uv_async_cb) certificate_check_async);
uv_async_send(&baton->req);
while(!baton->done) {
this_thread::sleep_for(chrono::milliseconds(1));
}
return baton->result;
}
void GitRemoteCallbacks::certificate_check_async(uv_async_t* req, int status)
{
NanScope();
CertificateCheckBaton* baton = static_cast<CertificateCheckBaton*>(req->data);
GitRemoteCallbacks* instance = static_cast<GitRemoteCallbacks*>(baton->payload);
if (instance->certificate_check->IsEmpty()) {
baton->result = 1; // no results acquired
baton->done = true;
return;
}
if (baton->cert == NULL) {
}
if (baton->valid == NULL) {
}
if (baton->host == NULL) {
baton->host = "";
}
Local<Value> argv[4] = {
NanNew(GitCert::New((void *)baton->cert, false)),
NanNew(baton->valid),
NanNew(baton->host),
NanNew(instance->payload)
};
TryCatch tryCatch;
Handle<v8::Value> result = instance->certificate_check->Call(4, argv);
if (result->IsObject() && result->ToObject()->Has(NanNew("then"))) {
Handle<v8::Value> thenProp = result->ToObject()->Get(NanNew("then"));
if (thenProp->IsFunction()) {
// we can be reasonbly certain that the result is a promise
Local<Object> promise = result->ToObject();
NanAssignPersistent(baton->promise, promise);
uv_async_init(uv_default_loop(), &baton->req, (uv_async_cb) certificate_check_asyncPromisePolling);
uv_async_send(&baton->req);
return;
}
}
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = -1;
} else if (!result->IsNull() && !result->IsUndefined()) {
if (result->IsNumber()) {
baton->result = (int)result->ToNumber()->Value();
} else {
baton->result = 1;
}
} else {
baton->result = 1;
}
baton->done = true;
NanReturnUndefined();
}
void GitRemoteCallbacks::certificate_check_asyncPromisePolling(uv_async_t* req, int status)
{
NanScope();
CertificateCheckBaton* baton = static_cast<CertificateCheckBaton*>(req->data);
Local<Object> promise = NanNew<Object>(baton->promise);
NanCallback* isPendingFn = new NanCallback(promise->Get(NanNew("isPending")).As<Function>());
Local<Value> argv[1]; // MSBUILD won't assign an array of length 0
Local<Boolean> isPending = isPendingFn->Call(0, argv)->ToBoolean();
if (isPending->Value()) {
uv_async_send(&baton->req);
return;
}
NanCallback* isFulfilledFn = new NanCallback(promise->Get(NanNew("isFulfilled")).As<Function>());
Local<Boolean> isFulfilled = isFulfilledFn->Call(0, argv)->ToBoolean();
if (isFulfilled->Value()) {
NanCallback* resultFn = new NanCallback(promise->Get(NanNew("value")).As<Function>());
Handle<v8::Value> result = resultFn->Call(0, argv);
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = -1;
} else if (!result->IsNull() && !result->IsUndefined()) {
if (result->IsNumber()) {
baton->result = (int)result->ToNumber()->Value();
} else {
baton->result = 1;
}
} else {
baton->result = 1;
}
baton->done = true;
} else {
// promise was rejected
baton->result = -1;
baton->done = false;
}
}
NAN_GETTER(GitRemoteCallbacks::GetTransferProgress)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
NanReturnValue(wrapper->transfer_progress->GetFunction());
}
NAN_SETTER(GitRemoteCallbacks::SetTransferProgress)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
if (wrapper->transfer_progress != NULL) {
delete wrapper->transfer_progress;
}
if (value->IsFunction()) {
if (!wrapper->raw->transfer_progress) {
wrapper->raw->transfer_progress = (git_transfer_progress_cb)transfer_progress_cppCallback;
}
wrapper->transfer_progress = new NanCallback(value.As<Function>());
}
}
int GitRemoteCallbacks::transfer_progress_cppCallback (
const git_transfer_progress * stats, void * payload )
{
TransferProgressBaton* baton = new TransferProgressBaton();
baton->stats = stats;
baton->payload = payload;
baton->result = 0;
baton->req.data = baton;
baton->done = false;
uv_async_init(uv_default_loop(), &baton->req, (uv_async_cb) transfer_progress_async);
uv_async_send(&baton->req);
while(!baton->done) {
this_thread::sleep_for(chrono::milliseconds(1));
}
return baton->result;
}
void GitRemoteCallbacks::transfer_progress_async(uv_async_t* req, int status)
{
NanScope();
TransferProgressBaton* baton = static_cast<TransferProgressBaton*>(req->data);
GitRemoteCallbacks* instance = static_cast<GitRemoteCallbacks*>(baton->payload);
if (instance->transfer_progress->IsEmpty()) {
baton->result = 0; // no results acquired
baton->done = true;
return;
}
if (baton->stats == NULL) {
}
Local<Value> argv[2] = {
NanNew(GitTransferProgress::New((void *)baton->stats, false)),
NanNew(instance->payload)
};
TryCatch tryCatch;
Handle<v8::Value> result = instance->transfer_progress->Call(2, argv);
if (result->IsObject() && result->ToObject()->Has(NanNew("then"))) {
Handle<v8::Value> thenProp = result->ToObject()->Get(NanNew("then"));
if (thenProp->IsFunction()) {
// we can be reasonbly certain that the result is a promise
Local<Object> promise = result->ToObject();
NanAssignPersistent(baton->promise, promise);
uv_async_init(uv_default_loop(), &baton->req, (uv_async_cb) transfer_progress_asyncPromisePolling);
uv_async_send(&baton->req);
return;
}
}
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = -1;
} else if (!result->IsNull() && !result->IsUndefined()) {
if (result->IsNumber()) {
baton->result = (int)result->ToNumber()->Value();
} else {
baton->result = 0;
}
} else {
baton->result = 0;
}
baton->done = true;
}
void GitRemoteCallbacks::transfer_progress_asyncPromisePolling(uv_async_t* req, int status)
{
NanScope();
TransferProgressBaton* baton = static_cast<TransferProgressBaton*>(req->data);
Local<Object> promise = NanNew<Object>(baton->promise);
NanCallback* isPendingFn = new NanCallback(promise->Get(NanNew("isPending")).As<Function>());
Local<Value> argv[1]; // MSBUILD won't assign an array of length 0
Local<Boolean> isPending = isPendingFn->Call(0, argv)->ToBoolean();
if (isPending->Value()) {
uv_async_send(&baton->req);
return;
}
NanCallback* isFulfilledFn = new NanCallback(promise->Get(NanNew("isFulfilled")).As<Function>());
Local<Boolean> isFulfilled = isFulfilledFn->Call(0, argv)->ToBoolean();
if (isFulfilled->Value()) {
NanCallback* resultFn = new NanCallback(promise->Get(NanNew("value")).As<Function>());
Handle<v8::Value> result = resultFn->Call(0, argv);
if (result.IsEmpty() || result->IsNativeError()) {
baton->result = -1;
} else if (!result->IsNull() && !result->IsUndefined()) {
if (result->IsNumber()) {
baton->result = (int)result->ToNumber()->Value();
} else {
baton->result = 0;
}
} else {
baton->result = 0;
}
baton->done = true;
} else {
// promise was rejected
baton->result = -1;
baton->done = false;
}
}
NAN_GETTER(GitRemoteCallbacks::GetPayload)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
NanReturnValue(wrapper->payload);
}
NAN_SETTER(GitRemoteCallbacks::SetPayload)
{
NanScope();
GitRemoteCallbacks *wrapper = ObjectWrap::Unwrap<GitRemoteCallbacks>(args.This());
NanAssignPersistent(wrapper->payload, value);
}
Persistent<Function> GitRemoteCallbacks::constructor_template;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment