Skip to content
Merged
77 changes: 75 additions & 2 deletions generate/input/descriptor.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@
}
},
"blob": {
"selfFreeing": true,
"functions": {
"git_blob_create_frombuffer": {
"isAsync": false,
Expand All @@ -140,6 +141,11 @@
"git_blob_filtered_content": {
"ignore": true
},
"git_blob_id": {
"return": {
"shouldDuplicate": true
}
},
"git_blob_rawcontent": {
"return": {
"cppClassName": "Wrapper",
Expand Down Expand Up @@ -354,6 +360,7 @@
}
},
"commit": {
"selfFreeing": true,
"functions": {
"git_commit_amend": {
"args": {
Expand All @@ -380,6 +387,16 @@
}
}
},
"git_commit_author": {
"return": {
"shouldDuplicate": true
}
},
"git_commit_committer": {
"return": {
"shouldDuplicate": true
}
},
"git_commit_create": {
"args": {
"id": {
Expand All @@ -404,6 +421,21 @@
},
"git_commit_create_from_ids": {
"ignore": true
},
"git_commit_id": {
"return": {
"shouldDuplicate": true
}
},
"git_commit_parent_id": {
"return": {
"shouldDuplicate": true
}
},
"git_commit_tree_id": {
"return": {
"shouldDuplicate": true
}
}
}
},
Expand Down Expand Up @@ -1273,6 +1305,8 @@
"ignore": true
},
"oid": {
"dupFunction": "git_oid_cpy",
"freeFunctionName": "free",
"shouldAlloc": true,
"functions": {
"git_oid_cpy": {
Expand Down Expand Up @@ -1877,6 +1911,7 @@
}
},
"signature": {
"dupFunction": "git_signature_dup",
"functions": {
"git_signature_default": {
"isAsync": false
Expand Down Expand Up @@ -2113,6 +2148,7 @@
}
},
"tag": {
"selfFreeing": true,
"functions": {
"git_tag_foreach": {
"ignore": true
Expand All @@ -2131,6 +2167,11 @@
"git_tag_create_frombuffer": {
"ignore": true
},
"git_tag_id": {
"return": {
"shouldDuplicate": true
}
},
"git_tag_create_lightweight": {
"args": {
"oid": {
Expand Down Expand Up @@ -2166,13 +2207,23 @@
},
"isAsync": true
},
"git_tag_tagger": {
"return": {
"shouldDuplicate": true
}
},
"git_tag_target": {
"args": {
"target_out": {
"isReturn": true
}
}
},
"git_tag_target_id": {
"return": {
"shouldDuplicate": true
}
},
"git_tag_delete": {
"return": {
"isErrorCode": true
Expand Down Expand Up @@ -2213,16 +2264,34 @@
]
},
"tree": {
"selfFreeing": true,
"functions": {
"git_tree_entry_free": {
"ignore": true
"git_tree_entry_byid": {
"return": {
"shouldDuplicate": true
}
},
"git_tree_entry_byindex": {
"jsFunctionName": "_entryByIndex"
},
"git_tree_entry_byname": {
"return": {
"shouldDuplicate": true
}
},
"git_tree_entry_id": {
"return": {
"shouldDuplicate": true
}
},
"git_tree_entrycount": {
"jsFunctionName": "entryCount"
},
"git_tree_id": {
"return": {
"shouldDuplicate": true
}
},
"git_tree_walk": {
"ignore": true
}
Expand All @@ -2249,6 +2318,10 @@
}
}
},
"tree_entry": {
"dupFunction": "git_tree_entry_dup",
"freeFunctionName": "git_tree_entry_free"
},
"writestream": {
"cType": "git_writestream",
"needsForwardDeclaration": false
Expand Down
1 change: 1 addition & 0 deletions generate/scripts/generateNativeCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ module.exports = function generateNativeCode() {
returnsCount: require("../templates/filters/returns_count"),
returnsInfo: require("../templates/filters/returns_info"),
titleCase: require("../templates/filters/title_case"),
toBool: require('../templates/filters/to_bool'),
unPointer: require("../templates/filters/un_pointer"),
upper: require("../templates/filters/upper")
};
Expand Down
14 changes: 13 additions & 1 deletion generate/scripts/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ var Helpers = {
}
},

// returns the libgittype found in types
decorateLibgitType: function(type, types, enums) {
var normalizedType = Helpers.normalizeCtype(type.cType);
var libgitType = Helpers.getLibgitType(normalizedType, types);
Expand All @@ -164,6 +165,8 @@ var Helpers = {
// we don't want to overwrite the c type of the passed in type
_.merge(type, descriptor.types[normalizedType.replace("git_", "")] || {}, { cType: type.cType });
}

return libgitType;
},

decoratePrimaryType: function(typeDef, enums) {
Expand All @@ -176,6 +179,11 @@ var Helpers = {
typeDef.filename = typeDef.typeName;
typeDef.isLibgitType = true;
typeDef.dependencies = [];
typeDef.selfFreeing = Boolean(typeDefOverrides.selfFreeing);

if (typeDefOverrides.freeFunctionName) {
typeDef.freeFunctionName = typeDefOverrides.freeFunctionName;
}

typeDef.fields = typeDef.fields || [];
typeDef.fields.forEach(function (field, index, allFields) {
Expand Down Expand Up @@ -241,7 +249,7 @@ var Helpers = {
arg.cppClassName = Helpers.cTypeToCppName(arg.cType);
arg.jsClassName = utils.titleCase(Helpers.cTypeToJsName(arg.cType));

Helpers.decorateLibgitType(arg, libgit2.types, enums);
var libgitType = Helpers.decorateLibgitType(arg, libgit2.types, enums);

// Some arguments can be callbacks
if (Helpers.isCallbackFunction(type)) {
Expand Down Expand Up @@ -271,6 +279,10 @@ var Helpers = {
_.every(allArgs, function(_arg) { return !_arg.isSelf; });
}

if (arg.isReturn && libgitType) {
arg.selfFreeing = libgitType.selfFreeing;
}

if (arg.isReturn && fnDef.return && fnDef.return.type === "int") {
fnDef.return.isErrorCode = true;
fnDef.isAsync = true;
Expand Down
3 changes: 3 additions & 0 deletions generate/templates/filters/to_bool.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function(value) {
return !!value;
};
2 changes: 1 addition & 1 deletion generate/templates/partials/convert_to_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
{% if cppClassName == 'Wrapper' %}
to = {{ cppClassName }}::New({{= parsedName =}});
{% else %}
to = {{ cppClassName }}::New({{= parsedName =}}, false);
to = {{ cppClassName }}::New({{= parsedName =}}, {{ selfFreeing|toBool }} {% if shouldDuplicate %}, true{% endif %});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{{ shouldDuplicate|toBool }}?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried it, but there is a case where we call that on something that I think is a struct. And I didn't want to add that parameter to struct constructors without adding support for it as well.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(so adding the 3rd parameter only whenshouldDuplicate is turned on avoids that problem)

{% endif %}
}
else {
Expand Down
49 changes: 43 additions & 6 deletions generate/templates/templates/class_content.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,34 @@ using namespace v8;
using namespace node;

{% if cType %}
{{ cppClassName }}::{{ cppClassName }}({{ cType }} *raw, bool selfFreeing) {
this->raw = raw;
{{ cppClassName }}::{{ cppClassName }}({{ cType }} *raw, bool selfFreeing, bool shouldDuplicate) {
if (shouldDuplicate) {
{% if shouldAlloc %}
this->raw = ({{ cType }} *)malloc(sizeof({{ cType }}));
{{ dupFunction }}(this->raw, raw);
{% else %}
{{ dupFunction }}(&this->raw, raw);
{% endif %}
selfFreeing = true;
} else {
this->raw = raw;
}
this->selfFreeing = selfFreeing;

if (selfFreeing) {
SelfFreeingInstanceCount++;
} else {
NonSelfFreeingConstructedCount++;
}

}

{{ cppClassName }}::~{{ cppClassName }}() {
{% if freeFunctionName %}
if (this->selfFreeing) {
{{ freeFunctionName }}(this->raw);
SelfFreeingInstanceCount--;

this->raw = NULL;
}
{% endif %}
Expand Down Expand Up @@ -77,6 +96,9 @@ using namespace node;
{% endif %}
{% endeach %}

Nan::SetMethod(tpl, "getSelfFreeingInstanceCount", GetSelfFreeingInstanceCount);
Nan::SetMethod(tpl, "getNonSelfFreeingConstructedCount", GetNonSelfFreeingConstructedCount);

Local<Function> _constructor_template = Nan::GetFunction(tpl).ToLocalChecked();
constructor_template.Reset(_constructor_template);
Nan::Set(target, Nan::New("{{ jsClassName }}").ToLocalChecked(), _constructor_template);
Expand All @@ -92,16 +114,28 @@ using namespace node;
{% endif %}
}

{{ cppClassName }}* object = new {{ cppClassName }}(static_cast<{{ cType }} *>(Local<External>::Cast(info[0])->Value()), Nan::To<bool>(info[1]).FromJust());
{{ cppClassName }}* object = new {{ cppClassName }}(static_cast<{{ cType }} *>(
Local<External>::Cast(info[0])->Value()),
Nan::To<bool>(info[1]).FromJust(),
info.Length() >= 3 ? Nan::To<bool>(info[2]).FromJust() : false
);
object->Wrap(info.This());

info.GetReturnValue().Set(info.This());
}

Local<v8::Value> {{ cppClassName }}::New(const {{ cType }} *raw, bool selfFreeing) {
Local<v8::Value> {{ cppClassName }}::New(const {{ cType }} *raw, bool selfFreeing, bool shouldDuplicate) {
Nan::EscapableHandleScope scope;
Local<v8::Value> argv[2] = { Nan::New<External>((void *)raw), Nan::New(selfFreeing) };
return scope.Escape(Nan::NewInstance(Nan::New({{ cppClassName }}::constructor_template), 2, argv).ToLocalChecked());
Local<v8::Value> argv[3] = { Nan::New<External>((void *)raw), Nan::New(selfFreeing), Nan::New(shouldDuplicate) };
return scope.Escape(Nan::NewInstance(Nan::New({{ cppClassName }}::constructor_template), 3, argv).ToLocalChecked());
}

NAN_METHOD({{ cppClassName }}::GetSelfFreeingInstanceCount) {
info.GetReturnValue().Set(SelfFreeingInstanceCount);
}

NAN_METHOD({{ cppClassName }}::GetNonSelfFreeingConstructedCount) {
info.GetReturnValue().Set(NonSelfFreeingConstructedCount);
}

{{ cType }} *{{ cppClassName }}::GetValue() {
Expand Down Expand Up @@ -147,3 +181,6 @@ using namespace node;
{% if not cTypeIsUndefined %}
Nan::Persistent<Function> {{ cppClassName }}::constructor_template;
{% endif %}

int {{ cppClassName }}::SelfFreeingInstanceCount;
int {{ cppClassName }}::NonSelfFreeingConstructedCount;
10 changes: 8 additions & 2 deletions generate/templates/templates/class_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,16 @@ class {{ cppClassName }} : public Nan::ObjectWrap {

static Nan::Persistent<Function> constructor_template;
static void InitializeComponent (Local<v8::Object> target);
// diagnostic count of self-freeing object instances
static int SelfFreeingInstanceCount;
// diagnostic count of constructed non-self-freeing object instances
static int NonSelfFreeingConstructedCount;

{%if cType%}
{{ cType }} *GetValue();
void ClearValue();

static Local<v8::Value> New(const {{ cType }} *raw, bool selfFreeing);
static Local<v8::Value> New(const {{ cType }} *raw, bool selfFreeing, bool shouldDuplicate = false);
{%endif%}
bool selfFreeing;

Expand Down Expand Up @@ -81,7 +85,7 @@ class {{ cppClassName }} : public Nan::ObjectWrap {


{%if cType%}
{{ cppClassName }}({{ cType }} *raw, bool selfFreeing);
{{ cppClassName }}({{ cType }} *raw, bool selfFreeing, bool shouldDuplicate = false);
~{{ cppClassName }}();
{%endif%}

Expand All @@ -96,6 +100,8 @@ class {{ cppClassName }} : public Nan::ObjectWrap {
{% endeach %}

static NAN_METHOD(JSNewFunction);
static NAN_METHOD(GetSelfFreeingInstanceCount);
static NAN_METHOD(GetNonSelfFreeingConstructedCount);

{%each fields as field%}
{%if not field.ignore%}
Expand Down
Loading