From b9146204b56c1f5e17195e68c0b33bc2e2c5a32e Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 15 Sep 2014 23:51:04 +0100 Subject: [PATCH 1/6] Porting to use Nan for node 0.11 compatability. --- .gitignore | 1 + binding.gyp | 3 + package.json | 11 +- src/tag.cc | 281 ++++++++++++++++++++++++++++++-------------------- src/tag.h | 59 +++++++---- src/taglib.cc | 108 ++++++++++--------- src/taglib.h | 15 ++- 7 files changed, 288 insertions(+), 190 deletions(-) diff --git a/.gitignore b/.gitignore index 866df99..3444544 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ spec/sample-write.mp3 node_modules .DS_Store spec/sample-write-async.mp3 +*.swp diff --git a/binding.gyp b/binding.gyp index 3211dd9..5bbe508 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,6 +4,9 @@ "target_name": "taglib", "sources": ["src/bufferstream.c", "src/tag.cc", "src/taglib.cc"], "libraries": ["=0.6.0", - "async" : ">=0.1.0", - "match-files" : "latest" + "vows": ">=0.6.0", + "async": ">=0.1.0", + "match-files": "latest" }, "scripts": { "test": "vows --spec" }, "engines": { - "node": ">=0.10.0 <0.11" + "node": ">=0.11.0" } } diff --git a/src/tag.cc b/src/tag.cc index 4c14333..3effcb1 100644 --- a/src/tag.cc +++ b/src/tag.cc @@ -14,30 +14,34 @@ using namespace node; namespace node_taglib { +static Local localTagTemplate; static Persistent TagTemplate; void Tag::Initialize(Handle target) { - HandleScope scope; + NanScope(); +// HandleScope scope; - TagTemplate = Persistent::New(FunctionTemplate::New()); + localTagTemplate = NanNew(); + NanAssignPersistent(TagTemplate, localTagTemplate); +// TagTemplate = Persistent::New(FunctionTemplate::New()); - TagTemplate->InstanceTemplate()->SetInternalFieldCount(1); - TagTemplate->SetClassName(String::NewSymbol("Tag")); + localTagTemplate->InstanceTemplate()->SetInternalFieldCount(1); +// localTagTemplate->SetClassName(String::NewSymbol("Tag")); - NODE_SET_PROTOTYPE_METHOD(TagTemplate, "save", AsyncSaveTag); - NODE_SET_PROTOTYPE_METHOD(TagTemplate, "saveSync", SyncSaveTag); - NODE_SET_PROTOTYPE_METHOD(TagTemplate, "isEmpty", IsEmpty); + NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "save", AsyncSaveTag); + NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "saveSync", SyncSaveTag); + NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "isEmpty", IsEmpty); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("album"), GetAlbum, SetAlbum); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("comment"), GetComment, SetComment); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("artist"), GetArtist, SetArtist); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("track"), GetTrack, SetTrack); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("year"), GetYear, SetYear); - TagTemplate->InstanceTemplate()->SetAccessor(String::New("genre"), GetGenre, SetGenre); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("title"), GetTitle, SetTitle); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("album"), GetAlbum, SetAlbum); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("comment"), GetComment, SetComment); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("artist"), GetArtist, SetArtist); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("track"), GetTrack, SetTrack); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("year"), GetYear, SetYear); + localTagTemplate->InstanceTemplate()->SetAccessor(NanNew("genre"), GetGenre, SetGenre); - target->Set(String::NewSymbol("Tag"), TagTemplate->GetFunction()); + target->Set(NanNew("Tag"), localTagTemplate->GetFunction()); NODE_SET_METHOD(target, "tag", AsyncTag); NODE_SET_METHOD(target, "tagSync", SyncTag); } @@ -51,102 +55,145 @@ Tag::~Tag() { tag = NULL; } -inline Tag * unwrapTag(const AccessorInfo& info) { - return ObjectWrap::Unwrap(info.Holder()); -} +//inline Tag * unwrapTag(const AccessorInfo& info) { +// return ObjectWrap::Unwrap(info.Holder()); +//} + +#define unwrapTag(info) ObjectWrap::Unwrap(info.Holder()) -Handle Tag::GetTitle(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->title())); +NAN_GETTER(Tag::GetTitle) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->title())); +//Handle Tag::GetTitle(Local property, const AccessorInfo& info) { +// HandleScope scope; +// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->title())); } -void Tag::SetTitle(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setTitle(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetTitle) { + NanScope(); +//void Tag::SetTitle(Local property, Local value, const AccessorInfo& info) { +// HandleScope scope; + unwrapTag(args)->tag->setTitle(NodeStringToTagLibString(value)); } -Handle Tag::GetArtist(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->artist())); +NAN_GETTER(Tag::GetArtist) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->artist())); +//Handle Tag::GetArtist(Local property, const AccessorInfo& info) { +// HandleScope scope; +// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->artist())); } -void Tag::SetArtist(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setArtist(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetArtist) { + NanScope(); +//void Tag::SetArtist(Local property, Local value, const AccessorInfo& info) { +// HandleScope scope; + unwrapTag(args)->tag->setArtist(NodeStringToTagLibString(value)); } -Handle Tag::GetAlbum(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->album())); +NAN_GETTER(Tag::GetAlbum) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->album())); +//Handle Tag::GetAlbum(Local property, const AccessorInfo& info) { +// HandleScope scope; +// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->album())); } -void Tag::SetAlbum(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setAlbum(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetAlbum) { + NanScope(); +//void Tag::SetAlbum(Local property, Local value, const AccessorInfo& info) { +// HandleScope scope; + unwrapTag(args)->tag->setAlbum(NodeStringToTagLibString(value)); } -Handle Tag::GetComment(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->comment())); +NAN_GETTER(Tag::GetComment) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->comment())); +//Handle Tag::GetComment(Local property, const AccessorInfo& info) { +// HandleScope scope; +// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->comment())); } -void Tag::SetComment(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setComment(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetComment) { + NanScope(); +//void Tag::SetComment(Local property, Local value, const AccessorInfo& info) { +// HandleScope scope; + unwrapTag(args)->tag->setComment(NodeStringToTagLibString(value)); } -Handle Tag::GetTrack(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(Integer::New(unwrapTag(info)->tag->track())); +NAN_GETTER(Tag::GetTrack) { + NanScope(); + NanReturnValue(NanNew(unwrapTag(args)->tag->track())); +//Handle Tag::GetTrack(Local property, const AccessorInfo& info) { +// HandleScope scope; +// return scope.Close(Integer::New(unwrapTag(info)->tag->track())); } -void Tag::SetTrack(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setTrack(value->IntegerValue()); +NAN_SETTER(Tag::SetTrack) { + NanScope(); +//void Tag::SetTrack(Local property, Local value, const AccessorInfo& info) { +// HandleScope scope; + unwrapTag(args)->tag->setTrack(value->IntegerValue()); } -Handle Tag::GetYear(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(Integer::New(unwrapTag(info)->tag->year())); +NAN_GETTER(Tag::GetYear) { + NanScope(); + NanReturnValue(NanNew(unwrapTag(args)->tag->year())); +//Handle Tag::GetYear(Local property, const AccessorInfo& info) { +// HandleScope scope; +// return scope.Close(Integer::New(unwrapTag(info)->tag->year())); } -void Tag::SetYear(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setYear(value->IntegerValue()); +NAN_SETTER(Tag::SetYear) { + NanScope(); +//void Tag::SetYear(Local property, Local value, const AccessorInfo& info) { +// HandleScope scope; + unwrapTag(args)->tag->setYear(value->IntegerValue()); } -Handle Tag::GetGenre(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->genre())); +NAN_GETTER(Tag::GetGenre) { + NanScope(); + NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->genre())); +//Handle Tag::GetGenre(Local property, const AccessorInfo& info) { +// HandleScope scope; +// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->genre())); } -void Tag::SetGenre(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; - unwrapTag(info)->tag->setGenre(NodeStringToTagLibString(value)); +NAN_SETTER(Tag::SetGenre) { + NanScope(); +//void Tag::SetGenre(Local property, Local value, const AccessorInfo& info) { +// HandleScope scope; + unwrapTag(args)->tag->setGenre(NodeStringToTagLibString(value)); } -Handle Tag::IsEmpty(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Tag::IsEmpty) { + NanScope(); +//Handle Tag::IsEmpty(const Arguments &args) { +// HandleScope scope; Tag *t = ObjectWrap::Unwrap(args.This()); - return Boolean::New(t->tag->isEmpty()); + NanReturnValue(NanNew(t->tag->isEmpty())); } -Handle Tag::SyncSaveTag(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Tag::SyncSaveTag) { + NanScope(); +//Handle Tag::SyncSaveTag(const Arguments &args) { +// HandleScope scope; Tag *t = ObjectWrap::Unwrap(args.This()); assert(t->fileRef); bool success = t->fileRef->save(); if (success) - return Undefined(); + NanReturnUndefined(); else - return ThrowException(String::Concat( - String::New("Failed to save file: "), - String::New(t->fileRef->file()->name()) + NanThrowError(String::Concat( + NanNew("Failed to save file: "), + NanNew(t->fileRef->file()->name()) )); } -Handle Tag::SyncTag(const Arguments &args) { - HandleScope scope; +NAN_METHOD(Tag::SyncTag) { + NanScope(); +//Handle Tag::SyncTag(const Arguments &args) { +// HandleScope scope; TagLib::FileRef *f = 0; int error = 0; @@ -154,49 +201,52 @@ Handle Tag::SyncTag(const Arguments &args) { if (args.Length() >= 1 && args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); if ((error = CreateFileRefPath(*path, &f))) { - Local fn = String::Concat(args[0]->ToString(), Local::Cast(String::New(": ", -1))); - return ThrowException(String::Concat(fn, ErrorToString(error))); + Local fn = String::Concat(args[0]->ToString(), Local::Cast(NanNew(": ", -1))); + NanThrowError(String::Concat(fn, ErrorToString(error))); } } else if (args.Length() >= 1 && Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - return ThrowException(String::New("Expected string 'format' as second argument")); + NanThrowError("Expected string 'format' as second argument"); if ((error = CreateFileRef(new BufferStream(args[0]->ToObject()), NodeStringToTagLibString(args[1]->ToString()), &f))) { - return ThrowException(ErrorToString(error)); + NanThrowError(ErrorToString(error)); } } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + NanThrowError("Expected string or buffer as first argument"); } Tag * tag = new Tag(f); - Handle inst = TagTemplate->InstanceTemplate()->NewInstance(); + Handle inst = localTagTemplate->InstanceTemplate()->NewInstance(); tag->Wrap(inst); - return scope.Close(inst); + NanReturnValue(inst); +// return scope.Close(inst); } -v8::Handle Tag::AsyncTag(const v8::Arguments &args) { - HandleScope scope; +NAN_METHOD(Tag::AsyncTag) { + NanScope(); +//v8::Handle Tag::AsyncTag(const v8::Arguments &args) { +// HandleScope scope; if (args.Length() < 1) { - return ThrowException(String::New("Expected string or buffer as first argument")); + NanThrowError("Expected string or buffer as first argument"); } if (args[0]->IsString()) { if (args.Length() < 2 || !args[1]->IsFunction()) - return ThrowException(String::New("Expected callback function as second argument")); + NanThrowError("Expected callback function as second argument"); } else if (Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - return ThrowException(String::New("Expected string 'format' as second argument")); + NanThrowError("Expected string 'format' as second argument"); if (args.Length() < 3 || !args[2]->IsFunction()) - return ThrowException(String::New("Expected callback function as third argument")); + NanThrowError("Expected callback function as third argument"); } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + NanThrowError("Expected string or buffer as first argument"); } @@ -209,18 +259,20 @@ v8::Handle Tag::AsyncTag(const v8::Arguments &args) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - baton->callback = Persistent::New(Local::Cast(args[1])); + baton->localCallback = Local::Cast(args[1]); + NanAssignPersistent(baton->callback, baton->localCallback); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - baton->callback = Persistent::New(Local::Cast(args[2])); + baton->localCallback = Local::Cast(args[2]); + NanAssignPersistent(baton->callback, baton->localCallback); } uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncTagReadDo, (uv_after_work_cb)Tag::AsyncTagReadAfter); - return Undefined(); + NanReturnUndefined(); } void Tag::AsyncTagReadDo(uv_work_t *req) { @@ -242,34 +294,39 @@ void Tag::AsyncTagReadDo(uv_work_t *req) { } void Tag::AsyncTagReadAfter(uv_work_t *req) { - HandleScope scope; + NanScope(); +// HandleScope scope; AsyncBaton *baton = static_cast(req->data); if (baton->error) { - Local error = Object::New(); - error->Set(String::New("code"), Integer::New(baton->error)); - error->Set(String::New("message"), ErrorToString(baton->error)); - Handle argv[] = { error, Null() }; - baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + Local error = NanNew(); + error->Set(NanNew("code"), NanNew(baton->error)); + error->Set(NanNew("message"), ErrorToString(baton->error)); + Handle argv[] = { error, NanNull() }; + baton->localCallback->Call(NanGetCurrentContext()->Global(), 2, argv); } else { - Persistent inst = Persistent::New(TagTemplate->InstanceTemplate()->NewInstance()); - baton->tag->Wrap(inst); - Handle argv[] = { Null(), inst }; - baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + Persistent inst; + Handle localInst = localTagTemplate->InstanceTemplate()->NewInstance(); + NanAssignPersistent(inst, localInst); + baton->tag->Wrap(localInst); + Handle argv[] = { NanNull(), localInst }; + baton->localCallback->Call(NanGetCurrentContext()->Global(), 2, argv); } - baton->callback.Dispose(); + NanDisposePersistent(baton->callback); delete baton->path; delete baton; } -v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { - HandleScope scope; +NAN_METHOD(AsyncSaveTag) { +//v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { + NanScope(); +// HandleScope scope; if (args.Length() >= 1 && !args[0]->IsFunction()) - return ThrowException(String::New("Expected callback function as first argument")); + NanThrowError("Expected callback function as first argument"); Local callback = Local::Cast(args[0]); @@ -278,12 +335,12 @@ v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { AsyncBaton *baton = new AsyncBaton; baton->request.data = baton; baton->tag = t; - baton->callback = Persistent::New(callback); + NanAssignPersistent(baton->callback, callback); baton->error = 1; uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncSaveTagDo, (uv_after_work_cb)Tag::AsyncSaveTagAfter); - return Undefined(); + NanReturnUndefined(); } void Tag::AsyncSaveTagDo(uv_work_t *req) { @@ -294,23 +351,23 @@ void Tag::AsyncSaveTagDo(uv_work_t *req) { } void Tag::AsyncSaveTagAfter(uv_work_t *req) { - HandleScope scope; + NanScope(); AsyncBaton *baton = static_cast(req->data); if (baton->error) { - Local error = Object::New(); - error->Set(String::New("message"), String::New("Failed to save file")); - error->Set(String::New("path"), String::New(baton->tag->fileRef->file()->name())); + Local error = NanNew(); + error->Set(NanNew("message"), NanNew("Failed to save file")); + error->Set(NanNew("path"), NanNew(baton->tag->fileRef->file()->name())); Handle argv[] = { error }; - baton->callback->Call(Context::GetCurrent()->Global(), 1, argv); + baton->localCallback->Call(NanGetCurrentContext()->Global(), 1, argv); } else { - Handle argv[] = { Null() }; - baton->callback->Call(Context::GetCurrent()->Global(), 1, argv); + Handle argv[] = { NanNull() }; + baton->localCallback->Call(NanGetCurrentContext()->Global(), 1, argv); } - baton->callback.Dispose(); + NanDisposePersistent(baton->callback); delete baton; } diff --git a/src/tag.h b/src/tag.h index f327b21..b4cf2c8 100644 --- a/src/tag.h +++ b/src/tag.h @@ -5,6 +5,8 @@ #include #include +#include + namespace node_taglib { class Tag : public node::ObjectWrap { TagLib::Tag * tag; @@ -17,32 +19,51 @@ class Tag : public node::ObjectWrap { Tag(TagLib::FileRef * fileRef); ~Tag(); - static v8::Handle GetTitle(v8::Local property, const v8::AccessorInfo& info); - static void SetTitle(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetTitle); + static NAN_SETTER(SetTitle); +// static v8::Handle GetTitle(v8::Local property, const v8::AccessorInfo& info); +// static void SetTitle(v8::Local property, v8::Local value, const v8::AccessorInfo& info); - static v8::Handle GetArtist(v8::Local property, const v8::AccessorInfo& info); - static void SetArtist(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetArtist); + static NAN_SETTER(SetArtist); +// static v8::Handle GetArtist(v8::Local property, const v8::AccessorInfo& info); +// static void SetArtist(v8::Local property, v8::Local value, const v8::AccessorInfo& info); - static v8::Handle GetAlbum(v8::Local property, const v8::AccessorInfo& info); - static void SetAlbum(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetAlbum); + static NAN_SETTER(SetAlbum); +// static v8::Handle GetAlbum(v8::Local property, const v8::AccessorInfo& info); +// static void SetAlbum(v8::Local property, v8::Local value, const v8::AccessorInfo& info); - static v8::Handle GetYear(v8::Local property, const v8::AccessorInfo& info); - static void SetYear(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetYear); + static NAN_SETTER(SetYear); +// static v8::Handle GetYear(v8::Local property, const v8::AccessorInfo& info); +// static void SetYear(v8::Local property, v8::Local value, const v8::AccessorInfo& info); - static v8::Handle GetComment(v8::Local property, const v8::AccessorInfo& info); - static void SetComment(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetComment); + static NAN_SETTER(SetComment); +// static v8::Handle GetComment(v8::Local property, const v8::AccessorInfo& info); +// static void SetComment(v8::Local property, v8::Local value, const v8::AccessorInfo& info); - static v8::Handle GetTrack(v8::Local property, const v8::AccessorInfo& info); - static void SetTrack(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetTrack); + static NAN_SETTER(SetTrack); +// static v8::Handle GetTrack(v8::Local property, const v8::AccessorInfo& info); +// static void SetTrack(v8::Local property, v8::Local value, const v8::AccessorInfo& info); - static v8::Handle GetGenre(v8::Local property, const v8::AccessorInfo& info); - static void SetGenre(v8::Local property, v8::Local value, const v8::AccessorInfo& info); + static NAN_GETTER(GetGenre); + static NAN_SETTER(SetGenre); +// static v8::Handle GetGenre(v8::Local property, const v8::AccessorInfo& info); +// static void SetGenre(v8::Local property, v8::Local value, const v8::AccessorInfo& info); - static v8::Handle IsEmpty(const v8::Arguments &args); - static v8::Handle AsyncSaveTag(const v8::Arguments &args); - static v8::Handle SyncSaveTag(const v8::Arguments &args); - static v8::Handle SyncTag(const v8::Arguments &args); - static v8::Handle AsyncTag(const v8::Arguments &args); + static NAN_METHOD(IsEmpty); + static NAN_METHOD(AsyncSaveTag); + static NAN_METHOD(SyncSaveTag); + static NAN_METHOD(SyncTag); + static NAN_METHOD(AsyncTag); +// static v8::Handle IsEmpty(const v8::Arguments &args); +// static v8::Handle AsyncSaveTag(const v8::Arguments &args); +// static v8::Handle SyncSaveTag(const v8::Arguments &args); +// static v8::Handle SyncTag(const v8::Arguments &args); +// static v8::Handle AsyncTag(const v8::Arguments &args); static void AsyncTagReadDo(uv_work_t *req); static void AsyncTagReadAfter(uv_work_t *req); static void AsyncSaveTagDo(uv_work_t *req); diff --git a/src/taglib.cc b/src/taglib.cc index b22dd6b..27cab69 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -131,7 +131,7 @@ TagLib::File *createFile(TagLib::IOStream *stream, TagLib::String format) { } Handle ErrorToString(int error) { - HandleScope scope; + NanEscapableScope(); std::string err; switch (error) { @@ -152,29 +152,32 @@ Handle ErrorToString(int error) { break; } - return scope.Close(String::New(err.c_str(), err.length())); + return NanEscapeScope(NanNew(err.c_str(), err.length())); +// return scope.Close(String::New(err.c_str(), err.length())); } -v8::Handle AsyncReadFile(const v8::Arguments &args) { - HandleScope scope; +NAN_METHOD(AsyncReadFile) { +//v8::Handle AsyncReadFile(const v8::Arguments &args) { + NanScope(); +// HandleScope scope; if (args.Length() < 1) { - return ThrowException(String::New("Expected string or buffer as first argument")); + NanThrowError("Expected string or buffer as first argument"); } if (args[0]->IsString()) { if (args.Length() < 2 || !args[1]->IsFunction()) - return ThrowException(String::New("Expected callback function as second argument")); + NanThrowError("Expected callback function as second argument"); } else if (Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - return ThrowException(String::New("Expected string 'format' as second argument")); + NanThrowError("Expected string 'format' as second argument"); if (args.Length() < 3 || !args[2]->IsFunction()) - return ThrowException(String::New("Expected callback function as third argument")); + NanThrowError("Expected callback function as third argument"); } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + NanThrowError("Expected string or buffer as first argument"); } AsyncBaton *baton = new AsyncBaton; @@ -187,18 +190,22 @@ v8::Handle AsyncReadFile(const v8::Arguments &args) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - baton->callback = Persistent::New(Local::Cast(args[1])); + baton->localCallback = Local::Cast(args[1]); + NanAssignPersistent(baton->callback, baton->localCallback); +// baton->callback = Persistent::New(baton->localCallback); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - baton->callback = Persistent::New(Local::Cast(args[2])); + baton->localCallback = Local::Cast(args[2]); + NanAssignPersistent(baton->callback, baton->localCallback); +// baton->callback = Persistent::New(Local::Cast(args[2])); } uv_queue_work(uv_default_loop(), &baton->request, AsyncReadFileDo, (uv_after_work_cb)AsyncReadFileAfter); - return Undefined(); + NanReturnUndefined(); } void AsyncReadFileDo(uv_work_t *req) { @@ -222,37 +229,37 @@ void AsyncReadFileDo(uv_work_t *req) { void AsyncReadFileAfter(uv_work_t *req) { AsyncBaton *baton = static_cast(req->data); if (baton->error) { - Local error = Object::New(); - error->Set(String::New("code"), Integer::New(baton->error)); - error->Set(String::New("message"), ErrorToString(baton->error)); - Handle argv[] = { error, Null(), Null() }; - baton->callback->Call(Context::GetCurrent()->Global(), 3, argv); + Local error = NanNew(); + error->Set(NanNew("code"), NanNew(baton->error)); + error->Set(NanNew("message"), ErrorToString(baton->error)); + Handle argv[] = { error, NanNull(), NanNull() }; + baton->localCallback->Call(NanGetCurrentContext()->Global(), 3, argv); } else { // read the data, put it in objects and delete the fileref TagLib::Tag *tag = baton->fileRef->tag(); - Local tagObj = Object::New(); + Local tagObj = NanNew(); if (!tag->isEmpty()) { - tagObj->Set(String::New("album"), TagLibStringToString(tag->album())); - tagObj->Set(String::New("artist"), TagLibStringToString(tag->artist())); - tagObj->Set(String::New("comment"), TagLibStringToString(tag->comment())); - tagObj->Set(String::New("genre"), TagLibStringToString(tag->genre())); - tagObj->Set(String::New("title"), TagLibStringToString(tag->title())); - tagObj->Set(String::New("track"), Integer::New(tag->track())); - tagObj->Set(String::New("year"), Integer::New(tag->year())); + tagObj->Set(NanNew("album"), TagLibStringToString(tag->album())); + tagObj->Set(NanNew("artist"), TagLibStringToString(tag->artist())); + tagObj->Set(NanNew("comment"), TagLibStringToString(tag->comment())); + tagObj->Set(NanNew("genre"), TagLibStringToString(tag->genre())); + tagObj->Set(NanNew("title"), TagLibStringToString(tag->title())); + tagObj->Set(NanNew("track"), NanNew(tag->track())); + tagObj->Set(NanNew("year"), NanNew(tag->year())); } TagLib::AudioProperties *props = baton->fileRef->audioProperties(); - Local propsObj = Object::New(); + Local propsObj = NanNew(); if (props) { - propsObj->Set(String::New("length"), Integer::New(props->length())); - propsObj->Set(String::New("bitrate"), Integer::New(props->bitrate())); - propsObj->Set(String::New("sampleRate"), Integer::New(props->sampleRate())); - propsObj->Set(String::New("channels"), Integer::New(props->channels())); + propsObj->Set(NanNew("length"), NanNew(props->length())); + propsObj->Set(NanNew("bitrate"), NanNew(props->bitrate())); + propsObj->Set(NanNew("sampleRate"), NanNew(props->sampleRate())); + propsObj->Set(NanNew("channels"), NanNew(props->channels())); } - Handle argv[] = { Null(), tagObj, propsObj }; - baton->callback->Call(Context::GetCurrent()->Global(), 3, argv); + Handle argv[] = { NanNull(), tagObj, propsObj }; + baton->localCallback->Call(NanGetCurrentContext()->Global(), 3, argv); delete baton->fileRef; delete baton; @@ -263,13 +270,13 @@ void AsyncReadFileAfter(uv_work_t *req) { Handle TagLibStringToString( TagLib::String s ) { if(s.isEmpty()) { - return Null(); + return NanNull(); } else { TagLib::ByteVector str = s.data(TagLib::String::UTF16); // Strip the Byte Order Mark of the input to avoid node adding a UTF-8 // Byte Order Mark - return String::New((uint16_t *)str.mid(2,str.size()-2).data(), s.size()); + return NanNew((uint16_t *)str.mid(2,str.size()-2).data(), s.size()); } } @@ -284,21 +291,21 @@ TagLib::String NodeStringToTagLibString( Local s ) } } -Handle AddResolvers(const Arguments &args) +//Handle AddResolvers(const Arguments &args) +NAN_METHOD(AddResolvers) { for (int i = 0; i < args.Length(); i++) { Local arg = args[i]; if (arg->IsFunction()) { - Persistent resolver = Persistent::New(Local::Cast(arg)); - TagLib::FileRef::addFileTypeResolver(new CallbackResolver(resolver)); + TagLib::FileRef::addFileTypeResolver(new CallbackResolver(Local::Cast(arg))); } } - return Undefined(); + NanReturnUndefined(); } -CallbackResolver::CallbackResolver(Persistent func) +CallbackResolver::CallbackResolver(Handle localFunc) : TagLib::FileRef::FileTypeResolver() - , resolverFunc(func) + , localResolverFunc(localFunc) // the constructor is always called in the v8 thread #ifdef _WIN32 , created_in(GetCurrentThreadId()) @@ -306,9 +313,10 @@ CallbackResolver::CallbackResolver(Persistent func) , created_in(pthread_self()) #endif { + NanAssignPersistent(resolverFunc, localResolverFunc); } -void CallbackResolver::invokeResolverCb(uv_async_t *handle, int status) +void CallbackResolver::invokeResolverCb(uv_async_t *handle) { AsyncResolverBaton *baton = (AsyncResolverBaton *) handle->data; invokeResolver(baton); @@ -316,16 +324,17 @@ void CallbackResolver::invokeResolverCb(uv_async_t *handle, int status) uv_close((uv_handle_t*)&baton->request, 0); } -void CallbackResolver::stopIdling(uv_async_t *handle, int status) +void CallbackResolver::stopIdling(uv_async_t *handle) { uv_close((uv_handle_t*) handle, 0); } void CallbackResolver::invokeResolver(AsyncResolverBaton *baton) { - HandleScope scope; + NanScope(); +// HandleScope scope; Handle argv[] = { TagLibStringToString(baton->fileName) }; - Local ret = baton->resolver->resolverFunc->Call(Context::GetCurrent()->Global(), 1, argv); + Local ret = baton->resolver->localResolverFunc->Call(NanGetCurrentContext()->Global(), 1, argv); if (!ret->IsString()) { baton->type = TagLib::String::null; } @@ -369,18 +378,19 @@ extern "C" { static void init (Handle target) { - HandleScope scope; + NanScope(); +// HandleScope scope; #ifdef TAGLIB_WITH_ASF - target->Set(String::NewSymbol("WITH_ASF"), v8::True()); + target->Set(NanNew("WITH_ASF"), NanTrue()); #else - target->Set(String::NewSymbol("WITH_ASF"), v8::False()); + target->Set(NanNew("WITH_ASF"), NanFalse()); #endif #ifdef TAGLIB_WITH_MP4 - target->Set(String::NewSymbol("WITH_MP4"), v8::True()); + target->Set(NanNew("WITH_MP4"), NanTrue()); #else - target->Set(String::NewSymbol("WITH_MP4"), v8::False()); + target->Set(NanNew("WITH_MP4"), NanFalse()); #endif NODE_SET_METHOD(target, "read", AsyncReadFile); diff --git a/src/taglib.h b/src/taglib.h index 1fa7b45..fbc5b1c 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -23,13 +24,15 @@ TagLib::File *createFile(TagLib::IOStream *stream, TagLib::String format); v8::Handle ErrorToString(int error); v8::Handle TagLibStringToString( TagLib::String s ); TagLib::String NodeStringToTagLibString( v8::Local s ); -v8::Handle AsyncReadFile(const v8::Arguments &args); +NAN_METHOD(AsyncReadFile); +//v8::Handle AsyncReadFile(const v8::Arguments &args); void AsyncReadFileDo(uv_work_t *req); void AsyncReadFileAfter(uv_work_t *req); struct AsyncBaton { uv_work_t request; v8::Persistent callback; + v8::Handle localCallback; int error; TagLib::FileName path; /* only used by read/tag, not save */ @@ -43,7 +46,8 @@ struct AsyncBaton { Tag *tag; /* only used by taglib.tag */ }; -v8::Handle AddResolvers(const v8::Arguments &args); +NAN_METHOD(AddResolvers); +//v8::Handle AddResolvers(const v8::Arguments &args); class CallbackResolver; @@ -56,14 +60,15 @@ struct AsyncResolverBaton { }; class CallbackResolver : public TagLib::FileRef::FileTypeResolver { + v8::Handle localResolverFunc; v8::Persistent resolverFunc; const uv_thread_t created_in; public: - CallbackResolver(v8::Persistent func); + CallbackResolver(v8::Handle localFunc); TagLib::File *createFile(TagLib::FileName fileName, bool readAudioProperties, TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; - static void invokeResolverCb(uv_async_t *handle, int status); - static void stopIdling(uv_async_t *handle, int status); + static void invokeResolverCb(uv_async_t *handle); + static void stopIdling(uv_async_t *handle); static void invokeResolver(AsyncResolverBaton *baton); }; From 6bba897a53c706ead7a3a7dae7c02123c28769a9 Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 16 Sep 2014 03:02:51 +0100 Subject: [PATCH 2/6] Now passing tests. There were some errors with not declaring a nanscope. Also not returning on errors. --- src/tag.cc | 47 ++++++++++++++++++++++------------------------- src/taglib.cc | 34 ++++++++++++++++++---------------- src/taglib.h | 2 -- 3 files changed, 40 insertions(+), 43 deletions(-) diff --git a/src/tag.cc b/src/tag.cc index 3effcb1..cc6aceb 100644 --- a/src/tag.cc +++ b/src/tag.cc @@ -14,7 +14,6 @@ using namespace node; namespace node_taglib { -static Local localTagTemplate; static Persistent TagTemplate; void Tag::Initialize(Handle target) @@ -22,12 +21,12 @@ void Tag::Initialize(Handle target) NanScope(); // HandleScope scope; - localTagTemplate = NanNew(); + Local localTagTemplate = NanNew(); NanAssignPersistent(TagTemplate, localTagTemplate); // TagTemplate = Persistent::New(FunctionTemplate::New()); localTagTemplate->InstanceTemplate()->SetInternalFieldCount(1); -// localTagTemplate->SetClassName(String::NewSymbol("Tag")); + localTagTemplate->SetClassName(NanNew("Tag")); NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "save", AsyncSaveTag); NODE_SET_PROTOTYPE_METHOD(localTagTemplate, "saveSync", SyncSaveTag); @@ -184,7 +183,7 @@ NAN_METHOD(Tag::SyncSaveTag) { if (success) NanReturnUndefined(); else - NanThrowError(String::Concat( + return NanThrowError(String::Concat( NanNew("Failed to save file: "), NanNew(t->fileRef->file()->name()) )); @@ -202,23 +201,23 @@ NAN_METHOD(Tag::SyncTag) { String::Utf8Value path(args[0]->ToString()); if ((error = CreateFileRefPath(*path, &f))) { Local fn = String::Concat(args[0]->ToString(), Local::Cast(NanNew(": ", -1))); - NanThrowError(String::Concat(fn, ErrorToString(error))); + return NanThrowError(String::Concat(fn, ErrorToString(error))); } } else if (args.Length() >= 1 && Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - NanThrowError("Expected string 'format' as second argument"); + return NanThrowError("Expected string 'format' as second argument"); if ((error = CreateFileRef(new BufferStream(args[0]->ToObject()), NodeStringToTagLibString(args[1]->ToString()), &f))) { - NanThrowError(ErrorToString(error)); + return NanThrowError(ErrorToString(error)); } } else { - NanThrowError("Expected string or buffer as first argument"); + return NanThrowError("Expected string or buffer as first argument"); } Tag * tag = new Tag(f); - Handle inst = localTagTemplate->InstanceTemplate()->NewInstance(); + Handle inst = NanNew(TagTemplate)->InstanceTemplate()->NewInstance(); tag->Wrap(inst); NanReturnValue(inst); @@ -231,22 +230,22 @@ NAN_METHOD(Tag::AsyncTag) { // HandleScope scope; if (args.Length() < 1) { - NanThrowError("Expected string or buffer as first argument"); + return NanThrowError("Expected string or buffer as first argument"); } if (args[0]->IsString()) { if (args.Length() < 2 || !args[1]->IsFunction()) - NanThrowError("Expected callback function as second argument"); + return NanThrowError("Expected callback function as second argument"); } else if (Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - NanThrowError("Expected string 'format' as second argument"); + return NanThrowError("Expected string 'format' as second argument"); if (args.Length() < 3 || !args[2]->IsFunction()) - NanThrowError("Expected callback function as third argument"); + return NanThrowError("Expected callback function as third argument"); } else { - NanThrowError("Expected string or buffer as first argument"); + return NanThrowError("Expected string or buffer as first argument"); } @@ -259,15 +258,13 @@ NAN_METHOD(Tag::AsyncTag) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - baton->localCallback = Local::Cast(args[1]); - NanAssignPersistent(baton->callback, baton->localCallback); + NanAssignPersistent(baton->callback, Local::Cast(args[1])); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - baton->localCallback = Local::Cast(args[2]); - NanAssignPersistent(baton->callback, baton->localCallback); + NanAssignPersistent(baton->callback, Local::Cast(args[2])); } uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncTagReadDo, (uv_after_work_cb)Tag::AsyncTagReadAfter); @@ -304,15 +301,15 @@ void Tag::AsyncTagReadAfter(uv_work_t *req) { error->Set(NanNew("code"), NanNew(baton->error)); error->Set(NanNew("message"), ErrorToString(baton->error)); Handle argv[] = { error, NanNull() }; - baton->localCallback->Call(NanGetCurrentContext()->Global(), 2, argv); + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 2, argv); } else { Persistent inst; - Handle localInst = localTagTemplate->InstanceTemplate()->NewInstance(); + Handle localInst = NanNew(TagTemplate)->InstanceTemplate()->NewInstance(); NanAssignPersistent(inst, localInst); baton->tag->Wrap(localInst); Handle argv[] = { NanNull(), localInst }; - baton->localCallback->Call(NanGetCurrentContext()->Global(), 2, argv); + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 2, argv); } NanDisposePersistent(baton->callback); @@ -320,13 +317,13 @@ void Tag::AsyncTagReadAfter(uv_work_t *req) { delete baton; } -NAN_METHOD(AsyncSaveTag) { +NAN_METHOD(Tag::AsyncSaveTag) { //v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { NanScope(); // HandleScope scope; if (args.Length() >= 1 && !args[0]->IsFunction()) - NanThrowError("Expected callback function as first argument"); + return NanThrowError("Expected callback function as first argument"); Local callback = Local::Cast(args[0]); @@ -360,11 +357,11 @@ void Tag::AsyncSaveTagAfter(uv_work_t *req) { error->Set(NanNew("message"), NanNew("Failed to save file")); error->Set(NanNew("path"), NanNew(baton->tag->fileRef->file()->name())); Handle argv[] = { error }; - baton->localCallback->Call(NanGetCurrentContext()->Global(), 1, argv); + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 1, argv); } else { Handle argv[] = { NanNull() }; - baton->localCallback->Call(NanGetCurrentContext()->Global(), 1, argv); + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 1, argv); } NanDisposePersistent(baton->callback); diff --git a/src/taglib.cc b/src/taglib.cc index 27cab69..99021af 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -161,23 +161,24 @@ NAN_METHOD(AsyncReadFile) { NanScope(); // HandleScope scope; + if (args.Length() < 1) { - NanThrowError("Expected string or buffer as first argument"); + return NanThrowError("Expected string or buffer as first argument"); } if (args[0]->IsString()) { if (args.Length() < 2 || !args[1]->IsFunction()) - NanThrowError("Expected callback function as second argument"); + return NanThrowError("Expected callback function as second argument"); } else if (Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) - NanThrowError("Expected string 'format' as second argument"); + return NanThrowError("Expected string 'format' as second argument"); if (args.Length() < 3 || !args[2]->IsFunction()) - NanThrowError("Expected callback function as third argument"); + return NanThrowError("Expected callback function as third argument"); } else { - NanThrowError("Expected string or buffer as first argument"); + return NanThrowError("Expected string or buffer as first argument"); } AsyncBaton *baton = new AsyncBaton; @@ -190,16 +191,14 @@ NAN_METHOD(AsyncReadFile) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - baton->localCallback = Local::Cast(args[1]); - NanAssignPersistent(baton->callback, baton->localCallback); + NanAssignPersistent(baton->callback, Local::Cast(args[1])); // baton->callback = Persistent::New(baton->localCallback); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - baton->localCallback = Local::Cast(args[2]); - NanAssignPersistent(baton->callback, baton->localCallback); + NanAssignPersistent(baton->callback, Local::Cast(args[2])); // baton->callback = Persistent::New(Local::Cast(args[2])); } @@ -227,13 +226,14 @@ void AsyncReadFileDo(uv_work_t *req) { } void AsyncReadFileAfter(uv_work_t *req) { + NanScope(); AsyncBaton *baton = static_cast(req->data); if (baton->error) { Local error = NanNew(); error->Set(NanNew("code"), NanNew(baton->error)); error->Set(NanNew("message"), ErrorToString(baton->error)); Handle argv[] = { error, NanNull(), NanNull() }; - baton->localCallback->Call(NanGetCurrentContext()->Global(), 3, argv); + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 3, argv); } else { // read the data, put it in objects and delete the fileref @@ -259,7 +259,7 @@ void AsyncReadFileAfter(uv_work_t *req) { } Handle argv[] = { NanNull(), tagObj, propsObj }; - baton->localCallback->Call(NanGetCurrentContext()->Global(), 3, argv); + NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 3, argv); delete baton->fileRef; delete baton; @@ -269,6 +269,7 @@ void AsyncReadFileAfter(uv_work_t *req) { Handle TagLibStringToString( TagLib::String s ) { + NanEscapableScope(); if(s.isEmpty()) { return NanNull(); } @@ -276,7 +277,8 @@ Handle TagLibStringToString( TagLib::String s ) TagLib::ByteVector str = s.data(TagLib::String::UTF16); // Strip the Byte Order Mark of the input to avoid node adding a UTF-8 // Byte Order Mark - return NanNew((uint16_t *)str.mid(2,str.size()-2).data(), s.size()); + Handle v8string = NanNew((uint16_t *)str.mid(2,str.size()-2).data(), s.size()); + return NanEscapeScope(v8string); } } @@ -294,6 +296,7 @@ TagLib::String NodeStringToTagLibString( Local s ) //Handle AddResolvers(const Arguments &args) NAN_METHOD(AddResolvers) { + NanScope(); for (int i = 0; i < args.Length(); i++) { Local arg = args[i]; if (arg->IsFunction()) { @@ -303,9 +306,8 @@ NAN_METHOD(AddResolvers) NanReturnUndefined(); } -CallbackResolver::CallbackResolver(Handle localFunc) +CallbackResolver::CallbackResolver(Handle func) : TagLib::FileRef::FileTypeResolver() - , localResolverFunc(localFunc) // the constructor is always called in the v8 thread #ifdef _WIN32 , created_in(GetCurrentThreadId()) @@ -313,7 +315,7 @@ CallbackResolver::CallbackResolver(Handle localFunc) , created_in(pthread_self()) #endif { - NanAssignPersistent(resolverFunc, localResolverFunc); + NanAssignPersistent(resolverFunc, func); } void CallbackResolver::invokeResolverCb(uv_async_t *handle) @@ -334,7 +336,7 @@ void CallbackResolver::invokeResolver(AsyncResolverBaton *baton) NanScope(); // HandleScope scope; Handle argv[] = { TagLibStringToString(baton->fileName) }; - Local ret = baton->resolver->localResolverFunc->Call(NanGetCurrentContext()->Global(), 1, argv); + Local ret = NanNew(baton->resolver->resolverFunc)->Call(NanGetCurrentContext()->Global(), 1, argv); if (!ret->IsString()) { baton->type = TagLib::String::null; } diff --git a/src/taglib.h b/src/taglib.h index fbc5b1c..e188296 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -32,7 +32,6 @@ void AsyncReadFileAfter(uv_work_t *req); struct AsyncBaton { uv_work_t request; v8::Persistent callback; - v8::Handle localCallback; int error; TagLib::FileName path; /* only used by read/tag, not save */ @@ -60,7 +59,6 @@ struct AsyncResolverBaton { }; class CallbackResolver : public TagLib::FileRef::FileTypeResolver { - v8::Handle localResolverFunc; v8::Persistent resolverFunc; const uv_thread_t created_in; From 0c54d155657f14550b12740a0071bed5446f313a Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 16 Sep 2014 03:37:04 +0100 Subject: [PATCH 3/6] fixed indentation for my changes (hopefully) --- src/tag.cc | 95 ++++++++++++--------------------------------------- src/taglib.cc | 14 ++------ 2 files changed, 24 insertions(+), 85 deletions(-) diff --git a/src/tag.cc b/src/tag.cc index cc6aceb..a83f49f 100644 --- a/src/tag.cc +++ b/src/tag.cc @@ -18,12 +18,10 @@ static Persistent TagTemplate; void Tag::Initialize(Handle target) { - NanScope(); -// HandleScope scope; + NanScope(); - Local localTagTemplate = NanNew(); - NanAssignPersistent(TagTemplate, localTagTemplate); -// TagTemplate = Persistent::New(FunctionTemplate::New()); + Local localTagTemplate = NanNew(); + NanAssignPersistent(TagTemplate, localTagTemplate); localTagTemplate->InstanceTemplate()->SetInternalFieldCount(1); localTagTemplate->SetClassName(NanNew("Tag")); @@ -54,136 +52,93 @@ Tag::~Tag() { tag = NULL; } -//inline Tag * unwrapTag(const AccessorInfo& info) { -// return ObjectWrap::Unwrap(info.Holder()); -//} - #define unwrapTag(info) ObjectWrap::Unwrap(info.Holder()) NAN_GETTER(Tag::GetTitle) { NanScope(); NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->title())); -//Handle Tag::GetTitle(Local property, const AccessorInfo& info) { -// HandleScope scope; -// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->title())); } NAN_SETTER(Tag::SetTitle) { NanScope(); -//void Tag::SetTitle(Local property, Local value, const AccessorInfo& info) { -// HandleScope scope; - unwrapTag(args)->tag->setTitle(NodeStringToTagLibString(value)); + unwrapTag(args)->tag->setTitle(NodeStringToTagLibString(value)); } NAN_GETTER(Tag::GetArtist) { NanScope(); NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->artist())); -//Handle Tag::GetArtist(Local property, const AccessorInfo& info) { -// HandleScope scope; -// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->artist())); } NAN_SETTER(Tag::SetArtist) { NanScope(); -//void Tag::SetArtist(Local property, Local value, const AccessorInfo& info) { -// HandleScope scope; - unwrapTag(args)->tag->setArtist(NodeStringToTagLibString(value)); + unwrapTag(args)->tag->setArtist(NodeStringToTagLibString(value)); } NAN_GETTER(Tag::GetAlbum) { NanScope(); NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->album())); -//Handle Tag::GetAlbum(Local property, const AccessorInfo& info) { -// HandleScope scope; -// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->album())); } NAN_SETTER(Tag::SetAlbum) { NanScope(); -//void Tag::SetAlbum(Local property, Local value, const AccessorInfo& info) { -// HandleScope scope; - unwrapTag(args)->tag->setAlbum(NodeStringToTagLibString(value)); + unwrapTag(args)->tag->setAlbum(NodeStringToTagLibString(value)); } NAN_GETTER(Tag::GetComment) { NanScope(); NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->comment())); -//Handle Tag::GetComment(Local property, const AccessorInfo& info) { -// HandleScope scope; -// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->comment())); } NAN_SETTER(Tag::SetComment) { NanScope(); -//void Tag::SetComment(Local property, Local value, const AccessorInfo& info) { -// HandleScope scope; - unwrapTag(args)->tag->setComment(NodeStringToTagLibString(value)); + unwrapTag(args)->tag->setComment(NodeStringToTagLibString(value)); } NAN_GETTER(Tag::GetTrack) { NanScope(); NanReturnValue(NanNew(unwrapTag(args)->tag->track())); -//Handle Tag::GetTrack(Local property, const AccessorInfo& info) { -// HandleScope scope; -// return scope.Close(Integer::New(unwrapTag(info)->tag->track())); } NAN_SETTER(Tag::SetTrack) { NanScope(); -//void Tag::SetTrack(Local property, Local value, const AccessorInfo& info) { -// HandleScope scope; - unwrapTag(args)->tag->setTrack(value->IntegerValue()); + unwrapTag(args)->tag->setTrack(value->IntegerValue()); } NAN_GETTER(Tag::GetYear) { NanScope(); NanReturnValue(NanNew(unwrapTag(args)->tag->year())); -//Handle Tag::GetYear(Local property, const AccessorInfo& info) { -// HandleScope scope; -// return scope.Close(Integer::New(unwrapTag(info)->tag->year())); } NAN_SETTER(Tag::SetYear) { NanScope(); -//void Tag::SetYear(Local property, Local value, const AccessorInfo& info) { -// HandleScope scope; - unwrapTag(args)->tag->setYear(value->IntegerValue()); + unwrapTag(args)->tag->setYear(value->IntegerValue()); } NAN_GETTER(Tag::GetGenre) { NanScope(); NanReturnValue(TagLibStringToString(unwrapTag(args)->tag->genre())); -//Handle Tag::GetGenre(Local property, const AccessorInfo& info) { -// HandleScope scope; -// return scope.Close(TagLibStringToString(unwrapTag(info)->tag->genre())); } NAN_SETTER(Tag::SetGenre) { NanScope(); -//void Tag::SetGenre(Local property, Local value, const AccessorInfo& info) { -// HandleScope scope; - unwrapTag(args)->tag->setGenre(NodeStringToTagLibString(value)); + unwrapTag(args)->tag->setGenre(NodeStringToTagLibString(value)); } NAN_METHOD(Tag::IsEmpty) { NanScope(); -//Handle Tag::IsEmpty(const Arguments &args) { -// HandleScope scope; - Tag *t = ObjectWrap::Unwrap(args.This()); - NanReturnValue(NanNew(t->tag->isEmpty())); + Tag *t = ObjectWrap::Unwrap(args.This()); + NanReturnValue(NanNew(t->tag->isEmpty())); } NAN_METHOD(Tag::SyncSaveTag) { NanScope(); -//Handle Tag::SyncSaveTag(const Arguments &args) { -// HandleScope scope; - Tag *t = ObjectWrap::Unwrap(args.This()); - assert(t->fileRef); - bool success = t->fileRef->save(); - if (success) - NanReturnUndefined(); - else - return NanThrowError(String::Concat( + Tag *t = ObjectWrap::Unwrap(args.This()); + assert(t->fileRef); + bool success = t->fileRef->save(); + if (success) + NanReturnUndefined(); + else + return NanThrowError(String::Concat( NanNew("Failed to save file: "), NanNew(t->fileRef->file()->name()) )); @@ -191,8 +146,6 @@ NAN_METHOD(Tag::SyncSaveTag) { NAN_METHOD(Tag::SyncTag) { NanScope(); -//Handle Tag::SyncTag(const Arguments &args) { -// HandleScope scope; TagLib::FileRef *f = 0; int error = 0; @@ -221,13 +174,10 @@ NAN_METHOD(Tag::SyncTag) { tag->Wrap(inst); NanReturnValue(inst); -// return scope.Close(inst); } NAN_METHOD(Tag::AsyncTag) { NanScope(); -//v8::Handle Tag::AsyncTag(const v8::Arguments &args) { -// HandleScope scope; if (args.Length() < 1) { return NanThrowError("Expected string or buffer as first argument"); @@ -292,7 +242,6 @@ void Tag::AsyncTagReadDo(uv_work_t *req) { void Tag::AsyncTagReadAfter(uv_work_t *req) { NanScope(); -// HandleScope scope; AsyncBaton *baton = static_cast(req->data); @@ -305,8 +254,8 @@ void Tag::AsyncTagReadAfter(uv_work_t *req) { } else { Persistent inst; - Handle localInst = NanNew(TagTemplate)->InstanceTemplate()->NewInstance(); - NanAssignPersistent(inst, localInst); + Handle localInst = NanNew(TagTemplate)->InstanceTemplate()->NewInstance(); + NanAssignPersistent(inst, localInst); baton->tag->Wrap(localInst); Handle argv[] = { NanNull(), localInst }; NanNew(baton->callback)->Call(NanGetCurrentContext()->Global(), 2, argv); @@ -318,9 +267,7 @@ void Tag::AsyncTagReadAfter(uv_work_t *req) { } NAN_METHOD(Tag::AsyncSaveTag) { -//v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { NanScope(); -// HandleScope scope; if (args.Length() >= 1 && !args[0]->IsFunction()) return NanThrowError("Expected callback function as first argument"); diff --git a/src/taglib.cc b/src/taglib.cc index 99021af..060b4c9 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -153,13 +153,10 @@ Handle ErrorToString(int error) { } return NanEscapeScope(NanNew(err.c_str(), err.length())); -// return scope.Close(String::New(err.c_str(), err.length())); } NAN_METHOD(AsyncReadFile) { -//v8::Handle AsyncReadFile(const v8::Arguments &args) { - NanScope(); -// HandleScope scope; + NanScope(); if (args.Length() < 1) { @@ -191,15 +188,13 @@ NAN_METHOD(AsyncReadFile) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - NanAssignPersistent(baton->callback, Local::Cast(args[1])); -// baton->callback = Persistent::New(baton->localCallback); + NanAssignPersistent(baton->callback, Local::Cast(args[1])); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - NanAssignPersistent(baton->callback, Local::Cast(args[2])); -// baton->callback = Persistent::New(Local::Cast(args[2])); + NanAssignPersistent(baton->callback, Local::Cast(args[2])); } uv_queue_work(uv_default_loop(), &baton->request, AsyncReadFileDo, (uv_after_work_cb)AsyncReadFileAfter); @@ -293,7 +288,6 @@ TagLib::String NodeStringToTagLibString( Local s ) } } -//Handle AddResolvers(const Arguments &args) NAN_METHOD(AddResolvers) { NanScope(); @@ -334,7 +328,6 @@ void CallbackResolver::stopIdling(uv_async_t *handle) void CallbackResolver::invokeResolver(AsyncResolverBaton *baton) { NanScope(); -// HandleScope scope; Handle argv[] = { TagLibStringToString(baton->fileName) }; Local ret = NanNew(baton->resolver->resolverFunc)->Call(NanGetCurrentContext()->Global(), 1, argv); if (!ret->IsString()) { @@ -381,7 +374,6 @@ static void init (Handle target) { NanScope(); -// HandleScope scope; #ifdef TAGLIB_WITH_ASF target->Set(NanNew("WITH_ASF"), NanTrue()); From 10248279da98444847f98690a53cd904f24272ad Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 16 Sep 2014 15:22:02 +0100 Subject: [PATCH 4/6] Removed some commented out stuff from the non-nan version Also fixed a problem where empty tag values were not being returned properly. --- src/tag.h | 21 --------------------- src/taglib.cc | 2 +- src/taglib.h | 2 -- 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/tag.h b/src/tag.h index b4cf2c8..f3d9d41 100644 --- a/src/tag.h +++ b/src/tag.h @@ -12,8 +12,6 @@ class Tag : public node::ObjectWrap { TagLib::Tag * tag; TagLib::FileRef * fileRef; - //static v8::Persistent pft; - public: static void Initialize(v8::Handle target); Tag(TagLib::FileRef * fileRef); @@ -21,49 +19,30 @@ class Tag : public node::ObjectWrap { static NAN_GETTER(GetTitle); static NAN_SETTER(SetTitle); -// static v8::Handle GetTitle(v8::Local property, const v8::AccessorInfo& info); -// static void SetTitle(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static NAN_GETTER(GetArtist); static NAN_SETTER(SetArtist); -// static v8::Handle GetArtist(v8::Local property, const v8::AccessorInfo& info); -// static void SetArtist(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static NAN_GETTER(GetAlbum); static NAN_SETTER(SetAlbum); -// static v8::Handle GetAlbum(v8::Local property, const v8::AccessorInfo& info); -// static void SetAlbum(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static NAN_GETTER(GetYear); static NAN_SETTER(SetYear); -// static v8::Handle GetYear(v8::Local property, const v8::AccessorInfo& info); -// static void SetYear(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static NAN_GETTER(GetComment); static NAN_SETTER(SetComment); -// static v8::Handle GetComment(v8::Local property, const v8::AccessorInfo& info); -// static void SetComment(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static NAN_GETTER(GetTrack); static NAN_SETTER(SetTrack); -// static v8::Handle GetTrack(v8::Local property, const v8::AccessorInfo& info); -// static void SetTrack(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static NAN_GETTER(GetGenre); static NAN_SETTER(SetGenre); -// static v8::Handle GetGenre(v8::Local property, const v8::AccessorInfo& info); -// static void SetGenre(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static NAN_METHOD(IsEmpty); static NAN_METHOD(AsyncSaveTag); static NAN_METHOD(SyncSaveTag); static NAN_METHOD(SyncTag); static NAN_METHOD(AsyncTag); -// static v8::Handle IsEmpty(const v8::Arguments &args); -// static v8::Handle AsyncSaveTag(const v8::Arguments &args); -// static v8::Handle SyncSaveTag(const v8::Arguments &args); -// static v8::Handle SyncTag(const v8::Arguments &args); -// static v8::Handle AsyncTag(const v8::Arguments &args); static void AsyncTagReadDo(uv_work_t *req); static void AsyncTagReadAfter(uv_work_t *req); static void AsyncSaveTagDo(uv_work_t *req); diff --git a/src/taglib.cc b/src/taglib.cc index 060b4c9..693a85d 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -266,7 +266,7 @@ Handle TagLibStringToString( TagLib::String s ) { NanEscapableScope(); if(s.isEmpty()) { - return NanNull(); + return NanEscapeScope(NanNull()); } else { TagLib::ByteVector str = s.data(TagLib::String::UTF16); diff --git a/src/taglib.h b/src/taglib.h index e188296..e69155f 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -25,7 +25,6 @@ v8::Handle ErrorToString(int error); v8::Handle TagLibStringToString( TagLib::String s ); TagLib::String NodeStringToTagLibString( v8::Local s ); NAN_METHOD(AsyncReadFile); -//v8::Handle AsyncReadFile(const v8::Arguments &args); void AsyncReadFileDo(uv_work_t *req); void AsyncReadFileAfter(uv_work_t *req); @@ -46,7 +45,6 @@ struct AsyncBaton { }; NAN_METHOD(AddResolvers); -//v8::Handle AddResolvers(const v8::Arguments &args); class CallbackResolver; From 2f7d3cb17862f08011358ba908497b747b66276c Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 16 Sep 2014 19:36:45 +0100 Subject: [PATCH 5/6] Casting node callback functions rather than changing the sigs This means it works with 0.10 and 0.11 --- src/taglib.cc | 8 ++++---- src/taglib.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/taglib.cc b/src/taglib.cc index 693a85d..3671466 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -312,7 +312,7 @@ CallbackResolver::CallbackResolver(Handle func) NanAssignPersistent(resolverFunc, func); } -void CallbackResolver::invokeResolverCb(uv_async_t *handle) +void CallbackResolver::invokeResolverCb(uv_async_t *handle, int status) { AsyncResolverBaton *baton = (AsyncResolverBaton *) handle->data; invokeResolver(baton); @@ -320,7 +320,7 @@ void CallbackResolver::invokeResolverCb(uv_async_t *handle) uv_close((uv_handle_t*)&baton->request, 0); } -void CallbackResolver::stopIdling(uv_async_t *handle) +void CallbackResolver::stopIdling(uv_async_t *handle, int status) { uv_close((uv_handle_t*) handle, 0); } @@ -351,9 +351,9 @@ TagLib::File *CallbackResolver::createFile(TagLib::FileName fileName, bool readA if (created_in != pthread_self()) { #endif uv_loop_t *wait_loop = uv_loop_new(); - uv_async_init(wait_loop, &baton.idler, CallbackResolver::stopIdling); + uv_async_init(wait_loop, &baton.idler, (uv_async_cb) CallbackResolver::stopIdling); - uv_async_init(uv_default_loop(), &baton.request, invokeResolverCb); + uv_async_init(uv_default_loop(), &baton.request, (uv_async_cb) invokeResolverCb); uv_async_send(&baton.request); uv_run(wait_loop, UV_RUN_DEFAULT); uv_loop_delete(wait_loop); diff --git a/src/taglib.h b/src/taglib.h index e69155f..adbbc69 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -63,8 +63,8 @@ class CallbackResolver : public TagLib::FileRef::FileTypeResolver { public: CallbackResolver(v8::Handle localFunc); TagLib::File *createFile(TagLib::FileName fileName, bool readAudioProperties, TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; - static void invokeResolverCb(uv_async_t *handle); - static void stopIdling(uv_async_t *handle); + static void invokeResolverCb(uv_async_t *handle, int status); + static void stopIdling(uv_async_t *handle, int status); static void invokeResolver(AsyncResolverBaton *baton); }; From 512eebe8c47a48417dcfa6fd456cdc1464dd8681 Mon Sep 17 00:00:00 2001 From: Joe Date: Tue, 16 Sep 2014 19:46:35 +0100 Subject: [PATCH 6/6] changed node dependency version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b028e5b..1201348 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,6 @@ "test": "vows --spec" }, "engines": { - "node": ">=0.11.0" + "node": ">=0.10" } }