From 1de2b5682bf854ecd3cee7431a161fcffa774333 Mon Sep 17 00:00:00 2001 From: Benjamin Schmitz Date: Thu, 17 Mar 2016 12:25:22 +0100 Subject: [PATCH 1/5] begin rework for compatibility with new v8 APIs --- src/tag.cc | 206 +++++++++++++++++++++++++++++--------------------- src/tag.h | 40 +++++----- src/taglib.cc | 36 +++++---- src/taglib.h | 4 +- 4 files changed, 164 insertions(+), 122 deletions(-) diff --git a/src/tag.cc b/src/tag.cc index 4c14333..a94fa6a 100644 --- a/src/tag.cc +++ b/src/tag.cc @@ -18,26 +18,27 @@ static Persistent TagTemplate; void Tag::Initialize(Handle target) { - HandleScope scope; + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); - TagTemplate = Persistent::New(FunctionTemplate::New()); + TagTemplate = Persistent(isolate, FunctionTemplate::New(isolate)); - TagTemplate->InstanceTemplate()->SetInternalFieldCount(1); - TagTemplate->SetClassName(String::NewSymbol("Tag")); + TagTemplate.Get(isolate)->InstanceTemplate()->SetInternalFieldCount(1); + TagTemplate.Get(isolate)->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); - 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); + TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle); + TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("album"), GetAlbum, SetAlbum); + TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("comment"), GetComment, SetComment); + TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("artist"), GetArtist, SetArtist); + TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("track"), GetTrack, SetTrack); + TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("year"), GetYear, SetYear); + TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("genre"), GetGenre, SetGenre); - target->Set(String::NewSymbol("Tag"), TagTemplate->GetFunction()); + target->Set(String::NewSymbol("Tag"), TagTemplate.Get(isolate)->GetFunction()); NODE_SET_METHOD(target, "tag", AsyncTag); NODE_SET_METHOD(target, "tagSync", SyncTag); } @@ -51,102 +52,116 @@ Tag::~Tag() { tag = NULL; } -inline Tag * unwrapTag(const AccessorInfo& info) { +inline Tag * unwrapTag(const PropertyCallbackInfo& info) { return ObjectWrap::Unwrap(info.Holder()); } -Handle Tag::GetTitle(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->title())); +void Tag::GetTitle(Local property, const PropertyCallbackInfo& info) { + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->title())); } -void Tag::SetTitle(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; +void Tag::SetTitle(Local property, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); unwrapTag(info)->tag->setTitle(NodeStringToTagLibString(value)); } - -Handle Tag::GetArtist(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->artist())); +void Tag::GetArtist(Local property, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->artist())); } -void Tag::SetArtist(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; +void Tag::SetArtist(Local property, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); unwrapTag(info)->tag->setArtist(NodeStringToTagLibString(value)); } -Handle Tag::GetAlbum(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->album())); +void Tag::GetAlbum(Local property, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->album())); } -void Tag::SetAlbum(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; +void Tag::SetAlbum(Local property, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); unwrapTag(info)->tag->setAlbum(NodeStringToTagLibString(value)); } -Handle Tag::GetComment(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->comment())); +void Tag::GetComment(Local property, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->comment())); } -void Tag::SetComment(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; +void Tag::SetComment(Local property, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); unwrapTag(info)->tag->setComment(NodeStringToTagLibString(value)); } -Handle Tag::GetTrack(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(Integer::New(unwrapTag(info)->tag->track())); +void Tag::GetTrack(Local property, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + info.GetReturnValue().Set(Integer::New(unwrapTag(info)->tag->track())); } -void Tag::SetTrack(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; +void Tag::SetTrack(Local property, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); unwrapTag(info)->tag->setTrack(value->IntegerValue()); } -Handle Tag::GetYear(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(Integer::New(unwrapTag(info)->tag->year())); +void Tag::GetYear(Local property, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + info.GetReturnValue().Set(Integer::New(unwrapTag(info)->tag->year())); } -void Tag::SetYear(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; +void Tag::SetYear(Local property, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); unwrapTag(info)->tag->setYear(value->IntegerValue()); } -Handle Tag::GetGenre(Local property, const AccessorInfo& info) { - HandleScope scope; - return scope.Close(TagLibStringToString(unwrapTag(info)->tag->genre())); +void Tag::GetGenre(Local property, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->genre())); } -void Tag::SetGenre(Local property, Local value, const AccessorInfo& info) { - HandleScope scope; +void Tag::SetGenre(Local property, Local value, const PropertyCallbackInfo& info) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); unwrapTag(info)->tag->setGenre(NodeStringToTagLibString(value)); } -Handle Tag::IsEmpty(const Arguments &args) { - HandleScope scope; +void Tag::IsEmpty(const FunctionCallbackInfo &args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); Tag *t = ObjectWrap::Unwrap(args.This()); - return Boolean::New(t->tag->isEmpty()); + args.GetReturnValue().Set(Boolean::New(t->tag->isEmpty())); } -Handle Tag::SyncSaveTag(const Arguments &args) { - HandleScope scope; +void Tag::SyncSaveTag(const FunctionCallbackInfo &args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); Tag *t = ObjectWrap::Unwrap(args.This()); assert(t->fileRef); bool success = t->fileRef->save(); if (success) - return Undefined(); + args.GetReturnValue().SetUndefined(); else - return ThrowException(String::Concat( + isolate->ThrowException(String::Concat( String::New("Failed to save file: "), String::New(t->fileRef->file()->name()) )); } -Handle Tag::SyncTag(const Arguments &args) { - HandleScope scope; +void Tag::SyncTag(const FunctionCallbackInfo &args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); TagLib::FileRef *f = 0; int error = 0; @@ -155,48 +170,60 @@ Handle Tag::SyncTag(const Arguments &args) { 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))); + isolate->ThrowException(String::Concat(fn, ErrorToString(error))); + return; } } 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")); + if (args.Length() < 2 || !args[1]->IsString()) { + isolate->ThrowException(String::New("Expected string 'format' as second argument")); + return; + } if ((error = CreateFileRef(new BufferStream(args[0]->ToObject()), NodeStringToTagLibString(args[1]->ToString()), &f))) { - return ThrowException(ErrorToString(error)); + isolate->ThrowException(ErrorToString(error)); + return; } } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + isolate->ThrowException(String::New("Expected string or buffer as first argument")); + return; } Tag * tag = new Tag(f); Handle inst = TagTemplate->InstanceTemplate()->NewInstance(); tag->Wrap(inst); - return scope.Close(inst); + args.GetReturnValue().Set(inst); } -v8::Handle Tag::AsyncTag(const v8::Arguments &args) { - HandleScope scope; +void Tag::AsyncTag(const FunctionCallbackInfo &args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + if (args.Length() < 1) { - return ThrowException(String::New("Expected string or buffer as first argument")); + isolate->ThrowException(String::New("Expected string or buffer as first argument")); + return; } if (args[0]->IsString()) { - if (args.Length() < 2 || !args[1]->IsFunction()) - return ThrowException(String::New("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")); - if (args.Length() < 3 || !args[2]->IsFunction()) - return ThrowException(String::New("Expected callback function as third argument")); - } - else { - return ThrowException(String::New("Expected string or buffer as first argument")); + if (args.Length() < 2 || !args[1]->IsFunction()) { + isolate->ThrowException(String::New("Expected callback function as second argument")); + return; + } + } else if (Buffer::HasInstance(args[0])) { + if (args.Length() < 2 || !args[1]->IsString()) { + isolate->ThrowException(String::New("Expected string 'format' as second argument")); + return; + } + if (args.Length() < 3 || !args[2]->IsFunction()) { + isolate->ThrowException(String::New("Expected callback function as third argument")); + return; + } + } else { + isolate->ThrowException(String::New("Expected string or buffer as first argument")); + return; } @@ -220,7 +247,7 @@ v8::Handle Tag::AsyncTag(const v8::Arguments &args) { uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncTagReadDo, (uv_after_work_cb)Tag::AsyncTagReadAfter); - return Undefined(); + args.GetReturnValue().SetUndefined(); } void Tag::AsyncTagReadDo(uv_work_t *req) { @@ -242,7 +269,8 @@ void Tag::AsyncTagReadDo(uv_work_t *req) { } void Tag::AsyncTagReadAfter(uv_work_t *req) { - HandleScope scope; + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); AsyncBaton *baton = static_cast(req->data); @@ -265,11 +293,14 @@ void Tag::AsyncTagReadAfter(uv_work_t *req) { delete baton; } -v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { - HandleScope scope; +void Tag::AsyncSaveTag(const FunctionCallbackInfo &args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); - if (args.Length() >= 1 && !args[0]->IsFunction()) - return ThrowException(String::New("Expected callback function as first argument")); + if (args.Length() >= 1 && !args[0]->IsFunction()) { + isolate->ThrowException(String::New("Expected callback function as first argument")); + return; + } Local callback = Local::Cast(args[0]); @@ -283,7 +314,7 @@ v8::Handle Tag::AsyncSaveTag(const v8::Arguments &args) { uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncSaveTagDo, (uv_after_work_cb)Tag::AsyncSaveTagAfter); - return Undefined(); + args.GetReturnValue().SetUndefined(); } void Tag::AsyncSaveTagDo(uv_work_t *req) { @@ -294,7 +325,8 @@ void Tag::AsyncSaveTagDo(uv_work_t *req) { } void Tag::AsyncSaveTagAfter(uv_work_t *req) { - HandleScope scope; + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); AsyncBaton *baton = static_cast(req->data); diff --git a/src/tag.h b/src/tag.h index f327b21..749f3ce 100644 --- a/src/tag.h +++ b/src/tag.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include namespace node_taglib { @@ -17,32 +19,32 @@ 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 void GetTitle(v8::Local property, const v8::PropertyCallbackInfo& info); + static void SetTitle(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& 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 void GetArtist(v8::Local< v8::String > property, const v8::PropertyCallbackInfo< v8::Value >& info); + static void SetArtist(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& 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 void GetAlbum(v8::Local property, const v8::PropertyCallbackInfo& info); + static void SetAlbum(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& 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 void GetYear(v8::Local property, const v8::PropertyCallbackInfo& info); + static void SetYear(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& 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 void GetComment(v8::Local property, const v8::PropertyCallbackInfo& info); + static void SetComment(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& 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 void GetTrack(v8::Local property, const v8::PropertyCallbackInfo& info); + static void SetTrack(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& 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 void GetGenre(v8::Local property, const v8::PropertyCallbackInfo& info); + static void SetGenre(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& 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); + void IsEmpty(const v8::FunctionCallbackInfo< v8::Value >& args); + void AsyncSaveTag(const v8::FunctionCallbackInfo< v8::Value >& args); + void SyncSaveTag(const v8::FunctionCallbackInfo< v8::Value >& args); + void SyncTag(const v8::FunctionCallbackInfo< v8::Value >& args); + void AsyncTag(const v8::FunctionCallbackInfo< v8::Value >& 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..e680e50 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -155,26 +155,34 @@ Handle ErrorToString(int error) { return scope.Close(String::New(err.c_str(), err.length())); } -v8::Handle AsyncReadFile(const v8::Arguments &args) { - HandleScope scope; +void AsyncReadFile(const FunctionCallbackInfo &args) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); if (args.Length() < 1) { - return ThrowException(String::New("Expected string or buffer as first argument")); + isolate->ThrowException(String::New("Expected string or buffer as first argument")); + return; } if (args[0]->IsString()) { - if (args.Length() < 2 || !args[1]->IsFunction()) - return ThrowException(String::New("Expected callback function as second argument")); - + if (args.Length() < 2 || !args[1]->IsFunction()) { + isolate->ThrowException(String::New("Expected callback function as second argument")); + return; + } } else if (Buffer::HasInstance(args[0])) { - if (args.Length() < 2 || !args[1]->IsString()) - return ThrowException(String::New("Expected string 'format' as second argument")); - if (args.Length() < 3 || !args[2]->IsFunction()) - return ThrowException(String::New("Expected callback function as third argument")); + if (args.Length() < 2 || !args[1]->IsString()) { + isolate->ThrowException(String::New("Expected string 'format' as second argument")); + return; + } + if (args.Length() < 3 || !args[2]->IsFunction()) { + isolate->ThrowException(String::New("Expected callback function as third argument")); + return; + } } else { - return ThrowException(String::New("Expected string or buffer as first argument")); + isolate->ThrowException(String::New("Expected string or buffer as first argument")); + return; } AsyncBaton *baton = new AsyncBaton; @@ -198,7 +206,7 @@ v8::Handle AsyncReadFile(const v8::Arguments &args) { uv_queue_work(uv_default_loop(), &baton->request, AsyncReadFileDo, (uv_after_work_cb)AsyncReadFileAfter); - return Undefined(); + args.GetReturnValue().SetUndefined(); } void AsyncReadFileDo(uv_work_t *req) { @@ -284,7 +292,7 @@ TagLib::String NodeStringToTagLibString( Local s ) } } -Handle AddResolvers(const Arguments &args) +void AddResolvers(const FunctionCallbackInfo &args) { for (int i = 0; i < args.Length(); i++) { Local arg = args[i]; @@ -293,7 +301,7 @@ Handle AddResolvers(const Arguments &args) TagLib::FileRef::addFileTypeResolver(new CallbackResolver(resolver)); } } - return Undefined(); + args.getReturnValue().SetUndefined(); } CallbackResolver::CallbackResolver(Persistent func) diff --git a/src/taglib.h b/src/taglib.h index 1fa7b45..bb54dcc 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -23,7 +23,7 @@ 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); +void AsyncReadFile(const v8::FunctionCallbackInfo< v8::Value > &args); void AsyncReadFileDo(uv_work_t *req); void AsyncReadFileAfter(uv_work_t *req); @@ -43,7 +43,7 @@ struct AsyncBaton { Tag *tag; /* only used by taglib.tag */ }; -v8::Handle AddResolvers(const v8::Arguments &args); +void AddResolvers(const v8::FunctionCallbackInfo< v8::Value >& args); class CallbackResolver; From 011dbe97b127289b7a8e8e51e0a08487692defc0 Mon Sep 17 00:00:00 2001 From: Benjamin Schmitz Date: Fri, 18 Mar 2016 16:08:11 +0100 Subject: [PATCH 2/5] redo; and use the nan compatibility layer --- binding.gyp | 1 + package.json | 9 +- src/tag.cc | 361 +++++++++++++++++++++----------------------------- src/tag.h | 75 ++++++----- src/taglib.cc | 95 +++++++------ src/taglib.h | 16 ++- 6 files changed, 259 insertions(+), 298 deletions(-) diff --git a/binding.gyp b/binding.gyp index 3211dd9..48c4875 100644 --- a/binding.gyp +++ b/binding.gyp @@ -4,6 +4,7 @@ "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" diff --git a/src/tag.cc b/src/tag.cc index a94fa6a..d1449e0 100644 --- a/src/tag.cc +++ b/src/tag.cc @@ -14,33 +14,27 @@ using namespace node; namespace node_taglib { -static Persistent TagTemplate; - -void Tag::Initialize(Handle target) -{ - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - - TagTemplate = Persistent(isolate, FunctionTemplate::New(isolate)); - - TagTemplate.Get(isolate)->InstanceTemplate()->SetInternalFieldCount(1); - TagTemplate.Get(isolate)->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); - - TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("title"), GetTitle, SetTitle); - TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("album"), GetAlbum, SetAlbum); - TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("comment"), GetComment, SetComment); - TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("artist"), GetArtist, SetArtist); - TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("track"), GetTrack, SetTrack); - TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("year"), GetYear, SetYear); - TagTemplate.Get(isolate)->InstanceTemplate()->SetAccessor(String::New("genre"), GetGenre, SetGenre); - - target->Set(String::NewSymbol("Tag"), TagTemplate.Get(isolate)->GetFunction()); - NODE_SET_METHOD(target, "tag", AsyncTag); - NODE_SET_METHOD(target, "tagSync", SyncTag); +NAN_MODULE_INIT(Tag::Init) { + v8::Local tpl = Nan::New(); + tpl->SetClassName(Nan::New("Tag").ToLocalChecked()); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + + Nan::SetPrototypeMethod(tpl, "save", AsyncSaveTag); + Nan::SetPrototypeMethod(tpl, "saveSync", SyncSaveTag); + Nan::SetPrototypeMethod(tpl, "isEmpty", IsEmpty); + + Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New("title").ToLocalChecked(), GetTitle, SetTitle); + Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New("album").ToLocalChecked(), GetAlbum, SetAlbum); + Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New("comment").ToLocalChecked(), GetComment, SetComment); + Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New("artist").ToLocalChecked(), GetArtist, SetArtist); + Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New("track").ToLocalChecked(), GetTrack, SetTrack); + Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New("year").ToLocalChecked(), GetYear, SetYear); + Nan::SetAccessor(tpl->InstanceTemplate(), Nan::New("genre").ToLocalChecked(), GetGenre, SetGenre); + + constructor().Reset(Nan::GetFunction(tpl).ToLocalChecked()); + Nan::Set(target, Nan::New("Tag").ToLocalChecked(), Nan::GetFunction(tpl).ToLocalChecked()); + Nan::SetMethod(target, "tag", AsyncTag); + Nan::SetMethod(target, "tagSync", SyncTag); } Tag::Tag(TagLib::FileRef * ffileRef) : tag(ffileRef->tag()), fileRef(ffileRef) { } @@ -52,177 +46,184 @@ Tag::~Tag() { tag = NULL; } -inline Tag * unwrapTag(const PropertyCallbackInfo& info) { - return ObjectWrap::Unwrap(info.Holder()); +inline Tag * unwrapTag(const Nan::PropertyCallbackInfo& info) { + return Nan::ObjectWrap::Unwrap(info.Holder()); } - -void Tag::GetTitle(Local property, const PropertyCallbackInfo& info) { - info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->title())); +inline Tag * unwrapTag(const Nan::PropertyCallbackInfo& info) { + return Nan::ObjectWrap::Unwrap(info.Holder()); } -void Tag::SetTitle(Local property, Local value, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - unwrapTag(info)->tag->setTitle(NodeStringToTagLibString(value)); + +NAN_GETTER(Tag::GetTitle) { + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->title())); } -void Tag::GetArtist(Local property, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->artist())); +NAN_SETTER(Tag::SetTitle) { + unwrapTag(info)->tag->setTitle(NodeStringToTagLibString(value)); } -void Tag::SetArtist(Local property, Local value, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - unwrapTag(info)->tag->setArtist(NodeStringToTagLibString(value)); +NAN_GETTER(Tag::GetArtist) { + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->artist())); } - -void Tag::GetAlbum(Local property, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->album())); +NAN_SETTER(Tag::SetArtist) { + unwrapTag(info)->tag->setArtist(NodeStringToTagLibString(value)); } -void Tag::SetAlbum(Local property, Local value, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - unwrapTag(info)->tag->setAlbum(NodeStringToTagLibString(value)); +NAN_GETTER(Tag::GetAlbum) { + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->album())); } - -void Tag::GetComment(Local property, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->comment())); +NAN_SETTER(Tag::SetAlbum) { + unwrapTag(info)->tag->setAlbum(NodeStringToTagLibString(value)); } -void Tag::SetComment(Local property, Local value, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - unwrapTag(info)->tag->setComment(NodeStringToTagLibString(value)); +NAN_GETTER(Tag::GetComment) { + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->comment())); } - -void Tag::GetTrack(Local property, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - info.GetReturnValue().Set(Integer::New(unwrapTag(info)->tag->track())); +NAN_SETTER(Tag::SetComment) { + unwrapTag(info)->tag->setComment(NodeStringToTagLibString(value)); } -void Tag::SetTrack(Local property, Local value, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - unwrapTag(info)->tag->setTrack(value->IntegerValue()); +NAN_GETTER(Tag::GetTrack) { + info.GetReturnValue().Set(unwrapTag(info)->tag->track()); +} +NAN_SETTER(Tag::SetTrack) { + unwrapTag(info)->tag->setTrack(value->IntegerValue()); } -void Tag::GetYear(Local property, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - info.GetReturnValue().Set(Integer::New(unwrapTag(info)->tag->year())); +NAN_GETTER(Tag::GetYear) { + info.GetReturnValue().Set(unwrapTag(info)->tag->year()); +} +NAN_SETTER(Tag::SetYear) { + unwrapTag(info)->tag->setYear(value->IntegerValue()); } -void Tag::SetYear(Local property, Local value, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - unwrapTag(info)->tag->setYear(value->IntegerValue()); +NAN_GETTER(Tag::GetGenre) { + info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->genre())); +} +NAN_SETTER(Tag::SetGenre) { + unwrapTag(info)->tag->setGenre(NodeStringToTagLibString(value)); } -void Tag::GetGenre(Local property, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - info.GetReturnValue().Set(TagLibStringToString(unwrapTag(info)->tag->genre())); +NAN_METHOD(Tag::IsEmpty) { + Tag *t = ObjectWrap::Unwrap(info.Holder()); + info.GetReturnValue().Set(t->tag->isEmpty()); } -void Tag::SetGenre(Local property, Local value, const PropertyCallbackInfo& info) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - unwrapTag(info)->tag->setGenre(NodeStringToTagLibString(value)); +NAN_METHOD(Tag::SyncSaveTag) { + Tag *t = ObjectWrap::Unwrap(info.Holder()); + assert(t->fileRef); + bool success = t->fileRef->save(); + if (success) + info.GetReturnValue().SetUndefined(); + else + Nan::ThrowError("Failed to save file."); + //TODO: filename } -void Tag::IsEmpty(const FunctionCallbackInfo &args) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - Tag *t = ObjectWrap::Unwrap(args.This()); - args.GetReturnValue().Set(Boolean::New(t->tag->isEmpty())); +NAN_METHOD(Tag::AsyncSaveTag) { + if (info.Length() >= 1 && !info[0]->IsFunction()) { + Nan::ThrowError("Expected callback function as first argument"); + return; + } + + Local callback = Local::Cast(info[0]); + + Tag *t = ObjectWrap::Unwrap(info.Holder()); + + AsyncBaton *baton = new AsyncBaton; + baton->request.data = baton; + baton->tag = t; + baton->callback.Reset(callback); + baton->error = 1; + + uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncSaveTagDo, (uv_after_work_cb)Tag::AsyncSaveTagAfter); + + info.GetReturnValue().SetUndefined(); } -void Tag::SyncSaveTag(const FunctionCallbackInfo &args) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - Tag *t = ObjectWrap::Unwrap(args.This()); - assert(t->fileRef); - bool success = t->fileRef->save(); - if (success) - args.GetReturnValue().SetUndefined(); - else - isolate->ThrowException(String::Concat( - String::New("Failed to save file: "), - String::New(t->fileRef->file()->name()) - )); +void Tag::AsyncSaveTagDo(uv_work_t *req) { + AsyncBaton *baton = static_cast(req->data); + + assert(baton->tag->fileRef); + baton->error = !baton->tag->fileRef->save(); } -void Tag::SyncTag(const FunctionCallbackInfo &args) { +void Tag::AsyncSaveTagAfter(uv_work_t *req) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); + AsyncBaton *baton = static_cast(req->data); + + if (baton->error) { + Local error = Nan::New(); + error->Set(Nan::New("message").ToLocalChecked(), Nan::New("Failed to save file").ToLocalChecked()); + error->Set(Nan::New("path").ToLocalChecked(), Nan::New(baton->tag->fileRef->file()->name()).ToLocalChecked()); + Handle argv[] = { error }; + Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->Global(), 1, argv); + } + else { + Handle argv[] = { Nan::Null() }; + Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->Global(), 1, argv); + } + + //baton->callback.Dispose(); + delete baton; +} + +NAN_METHOD(Tag::SyncTag) { TagLib::FileRef *f = 0; int error = 0; - if (args.Length() >= 1 && args[0]->IsString()) { - String::Utf8Value path(args[0]->ToString()); + if (info.Length() >= 1 && info[0]->IsString()) { + String::Utf8Value path(info[0]->ToString()); if ((error = CreateFileRefPath(*path, &f))) { - Local fn = String::Concat(args[0]->ToString(), Local::Cast(String::New(": ", -1))); - isolate->ThrowException(String::Concat(fn, ErrorToString(error))); + Local fn = String::Concat(info[0]->ToString(), Nan::New(": ", -1).ToLocalChecked()); + Nan::ThrowError(String::Concat(fn, ErrorToString(error))); return; } - } - else if (args.Length() >= 1 && Buffer::HasInstance(args[0])) { - if (args.Length() < 2 || !args[1]->IsString()) { - isolate->ThrowException(String::New("Expected string 'format' as second argument")); + } else if (info.Length() >= 1 && Buffer::HasInstance(info[0])) { + if (info.Length() < 2 || !info[1]->IsString()) { + Nan::ThrowError("Expected string 'format' as second argument"); return; } - if ((error = CreateFileRef(new BufferStream(args[0]->ToObject()), NodeStringToTagLibString(args[1]->ToString()), &f))) { - isolate->ThrowException(ErrorToString(error)); + if ((error = CreateFileRef(new BufferStream(info[0]->ToObject()), NodeStringToTagLibString(info[1]->ToString()), &f))) { + Nan::ThrowError(ErrorToString(error)); return; } - } - else { - isolate->ThrowException(String::New("Expected string or buffer as first argument")); + } else { + Nan::ThrowError("Expected string or buffer as first argument"); return; } Tag * tag = new Tag(f); - Handle inst = TagTemplate->InstanceTemplate()->NewInstance(); + Local inst = Nan::NewInstance(Nan::New(constructor())).ToLocalChecked(); tag->Wrap(inst); - args.GetReturnValue().Set(inst); + info.GetReturnValue().Set(inst); } -void Tag::AsyncTag(const FunctionCallbackInfo &args) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - - - if (args.Length() < 1) { - isolate->ThrowException(String::New("Expected string or buffer as first argument")); +NAN_METHOD(Tag::AsyncTag) { + if (info.Length() < 1) { + Nan::ThrowError("Expected string or buffer as first argument"); return; } - if (args[0]->IsString()) { - if (args.Length() < 2 || !args[1]->IsFunction()) { - isolate->ThrowException(String::New("Expected callback function as second argument")); + if (info[0]->IsString()) { + if (info.Length() < 2 || !info[1]->IsFunction()) { + Nan::ThrowError("Expected callback function as second argument"); return; } - } else if (Buffer::HasInstance(args[0])) { - if (args.Length() < 2 || !args[1]->IsString()) { - isolate->ThrowException(String::New("Expected string 'format' as second argument")); + } else if (Buffer::HasInstance(info[0])) { + if (info.Length() < 2 || !info[1]->IsString()) { + Nan::ThrowError("Expected string 'format' as second argument"); return; } - if (args.Length() < 3 || !args[2]->IsFunction()) { - isolate->ThrowException(String::New("Expected callback function as third argument")); + if (info.Length() < 3 || !info[2]->IsFunction()) { + Nan::ThrowError("Expected callback function as third argument"); return; } } else { - isolate->ThrowException(String::New("Expected string or buffer as first argument")); + Nan::ThrowError("Expected string or buffer as first argument"); return; } @@ -233,21 +234,21 @@ void Tag::AsyncTag(const FunctionCallbackInfo &args) { baton->tag = NULL; baton->error = 0; - if (args[0]->IsString()) { - String::Utf8Value path(args[0]->ToString()); + if (info[0]->IsString()) { + String::Utf8Value path(info[0]->ToString()); baton->path = strdup(*path); - baton->callback = Persistent::New(Local::Cast(args[1])); + baton->callback.Reset(Local::Cast(info[1])); } else { - baton->format = NodeStringToTagLibString(args[1]->ToString()); - baton->stream = new BufferStream(args[0]->ToObject()); - baton->callback = Persistent::New(Local::Cast(args[2])); + baton->format = NodeStringToTagLibString(info[1]->ToString()); + baton->stream = new BufferStream(info[0]->ToObject()); + baton->callback.Reset(Local::Cast(info[2])); } uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncTagReadDo, (uv_after_work_cb)Tag::AsyncTagReadAfter); - args.GetReturnValue().SetUndefined(); + info.GetReturnValue().SetUndefined(); } void Tag::AsyncTagReadDo(uv_work_t *req) { @@ -275,75 +276,21 @@ void Tag::AsyncTagReadAfter(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() }; - baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + Local error = Nan::New(); + error->Set(Nan::New("code").ToLocalChecked(), Nan::New(baton->error)); + error->Set(Nan::New("message").ToLocalChecked(), ErrorToString(baton->error)); + Handle argv[] = { error, Nan::Null() }; + Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->Global(), 2, argv); } else { - Persistent inst = Persistent::New(TagTemplate->InstanceTemplate()->NewInstance()); + Local inst = Nan::NewInstance(Nan::New(constructor())).ToLocalChecked(); baton->tag->Wrap(inst); - Handle argv[] = { Null(), inst }; - baton->callback->Call(Context::GetCurrent()->Global(), 2, argv); + Handle argv[] = { Nan::Null(), inst }; + Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->Global(), 2, argv); } - baton->callback.Dispose(); + //baton->callback.Dispose(); delete baton->path; delete baton; } - -void Tag::AsyncSaveTag(const FunctionCallbackInfo &args) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - - if (args.Length() >= 1 && !args[0]->IsFunction()) { - isolate->ThrowException(String::New("Expected callback function as first argument")); - return; - } - - Local callback = Local::Cast(args[0]); - - Tag *t = ObjectWrap::Unwrap(args.This()); - - AsyncBaton *baton = new AsyncBaton; - baton->request.data = baton; - baton->tag = t; - baton->callback = Persistent::New(callback); - baton->error = 1; - - uv_queue_work(uv_default_loop(), &baton->request, Tag::AsyncSaveTagDo, (uv_after_work_cb)Tag::AsyncSaveTagAfter); - - args.GetReturnValue().SetUndefined(); -} - -void Tag::AsyncSaveTagDo(uv_work_t *req) { - AsyncBaton *baton = static_cast(req->data); - - assert(baton->tag->fileRef); - baton->error = !baton->tag->fileRef->save(); -} - -void Tag::AsyncSaveTagAfter(uv_work_t *req) { - Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); - - 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())); - Handle argv[] = { error }; - baton->callback->Call(Context::GetCurrent()->Global(), 1, argv); - } - else { - Handle argv[] = { Null() }; - baton->callback->Call(Context::GetCurrent()->Global(), 1, argv); - } - - baton->callback.Dispose(); - delete baton; -} - } diff --git a/src/tag.h b/src/tag.h index 749f3ce..1c890d8 100644 --- a/src/tag.h +++ b/src/tag.h @@ -1,50 +1,61 @@ #ifndef NODE_TAGLIB_TAG_H #define NODE_TAGLIB_TAG_H +#include #include #include #include -#include #include +#include +#include + namespace node_taglib { -class Tag : public node::ObjectWrap { - TagLib::Tag * tag; - TagLib::FileRef * fileRef; +class Tag : public Nan::ObjectWrap { + +private: + TagLib::Tag * tag; + TagLib::FileRef *fileRef; //static v8::Persistent pft; - public: - static void Initialize(v8::Handle target); +public: + static NAN_MODULE_INIT(Init); Tag(TagLib::FileRef * fileRef); ~Tag(); + + static inline Nan::Persistent & constructor() { + static Nan::Persistent my_constructor; + return my_constructor; + } - static void GetTitle(v8::Local property, const v8::PropertyCallbackInfo& info); - static void SetTitle(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); - - static void GetArtist(v8::Local< v8::String > property, const v8::PropertyCallbackInfo< v8::Value >& info); - static void SetArtist(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); - - static void GetAlbum(v8::Local property, const v8::PropertyCallbackInfo& info); - static void SetAlbum(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); - - static void GetYear(v8::Local property, const v8::PropertyCallbackInfo& info); - static void SetYear(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); - - static void GetComment(v8::Local property, const v8::PropertyCallbackInfo& info); - static void SetComment(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); - - static void GetTrack(v8::Local property, const v8::PropertyCallbackInfo& info); - static void SetTrack(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); - - static void GetGenre(v8::Local property, const v8::PropertyCallbackInfo& info); - static void SetGenre(v8::Local property, v8::Local value, const v8::PropertyCallbackInfo& info); - - void IsEmpty(const v8::FunctionCallbackInfo< v8::Value >& args); - void AsyncSaveTag(const v8::FunctionCallbackInfo< v8::Value >& args); - void SyncSaveTag(const v8::FunctionCallbackInfo< v8::Value >& args); - void SyncTag(const v8::FunctionCallbackInfo< v8::Value >& args); - void AsyncTag(const v8::FunctionCallbackInfo< v8::Value >& args); + static NAN_GETTER(GetTitle); + static NAN_SETTER(SetTitle); + + static NAN_GETTER(GetArtist); + static NAN_SETTER(SetArtist); + + static NAN_GETTER(GetAlbum); + static NAN_SETTER(SetAlbum); + + static NAN_GETTER(GetYear); + static NAN_SETTER(SetYear); + + static NAN_GETTER(GetComment); + static NAN_SETTER(SetComment); + + static NAN_GETTER(GetTrack); + static NAN_SETTER(SetTrack); + + static NAN_GETTER(GetGenre); + static NAN_SETTER(SetGenre); + + static NAN_METHOD(IsEmpty); + static NAN_METHOD(AsyncSaveTag); + static NAN_METHOD(SyncSaveTag); + static NAN_METHOD(SyncTag); + static NAN_METHOD(AsyncTag); + 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 e680e50..6842395 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -130,8 +130,7 @@ TagLib::File *createFile(TagLib::IOStream *stream, TagLib::String format) { return file; } -Handle ErrorToString(int error) { - HandleScope scope; +Local< String > ErrorToString(int error) { std::string err; switch (error) { @@ -152,36 +151,36 @@ Handle ErrorToString(int error) { break; } - return scope.Close(String::New(err.c_str(), err.length())); + return Nan::New(err).ToLocalChecked(); } -void AsyncReadFile(const FunctionCallbackInfo &args) { +void AsyncReadFile(const Nan::FunctionCallbackInfo &args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); if (args.Length() < 1) { - isolate->ThrowException(String::New("Expected string or buffer as first argument")); + Nan::ThrowError("Expected string or buffer as first argument"); return; } if (args[0]->IsString()) { if (args.Length() < 2 || !args[1]->IsFunction()) { - isolate->ThrowException(String::New("Expected callback function as second argument")); + Nan::ThrowError("Expected callback function as second argument"); return; } } else if (Buffer::HasInstance(args[0])) { if (args.Length() < 2 || !args[1]->IsString()) { - isolate->ThrowException(String::New("Expected string 'format' as second argument")); + Nan::ThrowError("Expected string 'format' as second argument"); return; } if (args.Length() < 3 || !args[2]->IsFunction()) { - isolate->ThrowException(String::New("Expected callback function as third argument")); + Nan::ThrowError("Expected callback function as third argument"); return; } } else { - isolate->ThrowException(String::New("Expected string or buffer as first argument")); + Nan::ThrowError("Expected string or buffer as first argument"); return; } @@ -195,13 +194,13 @@ void AsyncReadFile(const FunctionCallbackInfo &args) { if (args[0]->IsString()) { String::Utf8Value path(args[0]->ToString()); baton->path = strdup(*path); - baton->callback = Persistent::New(Local::Cast(args[1])); + baton->callback.Reset(Local::Cast(args[1])); } else { baton->format = NodeStringToTagLibString(args[1]->ToString()); baton->stream = new BufferStream(args[0]->ToObject()); - baton->callback = Persistent::New(Local::Cast(args[2])); + baton->callback.Reset(Local::Cast(args[2])); } uv_queue_work(uv_default_loop(), &baton->request, AsyncReadFileDo, (uv_after_work_cb)AsyncReadFileAfter); @@ -230,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 = Nan::New(); + error->Set(Nan::New("code").ToLocalChecked(), Nan::New(baton->error)); + error->Set(Nan::New("message").ToLocalChecked(), ErrorToString(baton->error)); + Handle argv[] = { error, Nan::Null(), Nan::Null() }; + Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->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 = Nan::New(); 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(Nan::New("album").ToLocalChecked(), TagLibStringToString(tag->album())); + tagObj->Set(Nan::New("artist").ToLocalChecked(), TagLibStringToString(tag->artist())); + tagObj->Set(Nan::New("comment").ToLocalChecked(), TagLibStringToString(tag->comment())); + tagObj->Set(Nan::New("genre").ToLocalChecked(), TagLibStringToString(tag->genre())); + tagObj->Set(Nan::New("title").ToLocalChecked(), TagLibStringToString(tag->title())); + tagObj->Set(Nan::New("track").ToLocalChecked(), Nan::New(tag->track())); + tagObj->Set(Nan::New("year").ToLocalChecked(), Nan::New(tag->year())); } TagLib::AudioProperties *props = baton->fileRef->audioProperties(); - Local propsObj = Object::New(); + Local propsObj = Nan::New(); 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(Nan::New("length").ToLocalChecked(), Nan::New(props->length())); + propsObj->Set(Nan::New("bitrate").ToLocalChecked(), Nan::New(props->bitrate())); + propsObj->Set(Nan::New("sampleRate").ToLocalChecked(), Nan::New(props->sampleRate())); + propsObj->Set(Nan::New("channels").ToLocalChecked(), Nan::New(props->channels())); } - Handle argv[] = { Null(), tagObj, propsObj }; - baton->callback->Call(Context::GetCurrent()->Global(), 3, argv); + Handle argv[] = { Nan::Null(), tagObj, propsObj }; + Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->Global(), 3, argv); delete baton->fileRef; delete baton; @@ -268,16 +267,16 @@ void AsyncReadFileAfter(uv_work_t *req) { } } -Handle TagLibStringToString( TagLib::String s ) +Local< Value > TagLibStringToString( TagLib::String s ) { if(s.isEmpty()) { - return Null(); + return Nan::Null(); } 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 Nan::New((uint16_t *)str.mid(2,str.size()-2).data(), s.size()).ToLocalChecked(); } } @@ -292,19 +291,19 @@ TagLib::String NodeStringToTagLibString( Local s ) } } -void AddResolvers(const FunctionCallbackInfo &args) +void AddResolvers(const Nan::FunctionCallbackInfo &args) { for (int i = 0; i < args.Length(); i++) { Local arg = args[i]; if (arg->IsFunction()) { - Persistent resolver = Persistent::New(Local::Cast(arg)); + Nan::Persistent resolver(Local::Cast(arg)); TagLib::FileRef::addFileTypeResolver(new CallbackResolver(resolver)); } } - args.getReturnValue().SetUndefined(); + args.GetReturnValue().SetUndefined(); } -CallbackResolver::CallbackResolver(Persistent func) +CallbackResolver::CallbackResolver(Nan::Persistent func) : TagLib::FileRef::FileTypeResolver() , resolverFunc(func) // the constructor is always called in the v8 thread @@ -316,7 +315,7 @@ CallbackResolver::CallbackResolver(Persistent func) { } -void CallbackResolver::invokeResolverCb(uv_async_t *handle, int status) +void CallbackResolver::invokeResolverCb(uv_async_t *handle) { AsyncResolverBaton *baton = (AsyncResolverBaton *) handle->data; invokeResolver(baton); @@ -324,16 +323,16 @@ 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; + Nan::HandleScope scope; Handle argv[] = { TagLibStringToString(baton->fileName) }; - Local ret = baton->resolver->resolverFunc->Call(Context::GetCurrent()->Global(), 1, argv); + Local ret = Nan::Call(Nan::New(baton->resolver->resolverFunc), Nan::GetCurrentContext()->Global(), 1, argv).ToLocalChecked(); if (!ret->IsString()) { baton->type = TagLib::String::null; } @@ -377,25 +376,25 @@ extern "C" { static void init (Handle target) { - HandleScope scope; + Nan::HandleScope scope; #ifdef TAGLIB_WITH_ASF - target->Set(String::NewSymbol("WITH_ASF"), v8::True()); + target->Set(Nan::New("WITH_ASF").ToLocalChecked(), Nan::True()); #else - target->Set(String::NewSymbol("WITH_ASF"), v8::False()); + target->Set(Nan::New("WITH_ASF").ToLocalChecked(), Nan::False()); #endif #ifdef TAGLIB_WITH_MP4 - target->Set(String::NewSymbol("WITH_MP4"), v8::True()); + target->Set(Nan::New("WITH_MP4").ToLocalChecked(), Nan::True()); #else - target->Set(String::NewSymbol("WITH_MP4"), v8::False()); + target->Set(Nan::New("WITH_MP4").ToLocalChecked(), Nan::False()); #endif NODE_SET_METHOD(target, "read", AsyncReadFile); #ifdef ENABLE_RESOLVERS NODE_SET_METHOD(target, "addResolvers", AddResolvers); #endif - Tag::Initialize(target); + Tag::Init(target); } NODE_MODULE(taglib, init) diff --git a/src/taglib.h b/src/taglib.h index bb54dcc..61c7c2c 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -9,6 +9,8 @@ #include +#include + namespace node_taglib { class Tag; class BufferStream; @@ -20,8 +22,8 @@ class BufferStream; int CreateFileRefPath(TagLib::FileName path, TagLib::FileRef **ref); int CreateFileRef(TagLib::IOStream *stream, TagLib::String format, TagLib::FileRef **ref); TagLib::File *createFile(TagLib::IOStream *stream, TagLib::String format); -v8::Handle ErrorToString(int error); -v8::Handle TagLibStringToString( TagLib::String s ); +v8::Local ErrorToString(int error); +v8::Local TagLibStringToString( TagLib::String s ); TagLib::String NodeStringToTagLibString( v8::Local s ); void AsyncReadFile(const v8::FunctionCallbackInfo< v8::Value > &args); void AsyncReadFileDo(uv_work_t *req); @@ -29,7 +31,7 @@ void AsyncReadFileAfter(uv_work_t *req); struct AsyncBaton { uv_work_t request; - v8::Persistent callback; + Nan::Persistent callback; int error; TagLib::FileName path; /* only used by read/tag, not save */ @@ -56,14 +58,14 @@ struct AsyncResolverBaton { }; class CallbackResolver : public TagLib::FileRef::FileTypeResolver { - v8::Persistent resolverFunc; + Nan::Persistent resolverFunc; const uv_thread_t created_in; public: - CallbackResolver(v8::Persistent func); + CallbackResolver(Nan::Persistent func); 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 569d56971a827272262dd2a68dd7ad69644e9abb Mon Sep 17 00:00:00 2001 From: Benjamin Schmitz Date: Fri, 18 Mar 2016 16:12:44 +0100 Subject: [PATCH 3/5] fix compile --- src/taglib.cc | 4 ++-- src/taglib.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/taglib.cc b/src/taglib.cc index 6842395..ea8f478 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -296,14 +296,14 @@ void AddResolvers(const Nan::FunctionCallbackInfo &args) for (int i = 0; i < args.Length(); i++) { Local arg = args[i]; if (arg->IsFunction()) { - Nan::Persistent resolver(Local::Cast(arg)); + Local resolver = Local::Cast(arg); TagLib::FileRef::addFileTypeResolver(new CallbackResolver(resolver)); } } args.GetReturnValue().SetUndefined(); } -CallbackResolver::CallbackResolver(Nan::Persistent func) +CallbackResolver::CallbackResolver(Local< Function > func) : TagLib::FileRef::FileTypeResolver() , resolverFunc(func) // the constructor is always called in the v8 thread diff --git a/src/taglib.h b/src/taglib.h index 61c7c2c..1a3501e 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -62,7 +62,7 @@ class CallbackResolver : public TagLib::FileRef::FileTypeResolver { const uv_thread_t created_in; public: - CallbackResolver(Nan::Persistent func); + CallbackResolver(v8::Local func); 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); From 458231027549eb8caf302299d3178bcea3016214 Mon Sep 17 00:00:00 2001 From: Benjamin Schmitz Date: Fri, 18 Mar 2016 16:28:42 +0100 Subject: [PATCH 4/5] fix undefined symbol --- src/taglib.cc | 14 +++++++------- src/taglib.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/taglib.cc b/src/taglib.cc index ea8f478..5f7bd14 100644 --- a/src/taglib.cc +++ b/src/taglib.cc @@ -154,7 +154,7 @@ Local< String > ErrorToString(int error) { return Nan::New(err).ToLocalChecked(); } -void AsyncReadFile(const Nan::FunctionCallbackInfo &args) { +void AsyncReadFile(const Nan::FunctionCallbackInfo< v8::Value >& args) { Isolate* isolate = Isolate::GetCurrent(); HandleScope scope(isolate); @@ -379,20 +379,20 @@ init (Handle target) Nan::HandleScope scope; #ifdef TAGLIB_WITH_ASF - target->Set(Nan::New("WITH_ASF").ToLocalChecked(), Nan::True()); + Nan::Set(target, Nan::New("WITH_ASF").ToLocalChecked(), Nan::True()); #else - target->Set(Nan::New("WITH_ASF").ToLocalChecked(), Nan::False()); + Nan::Set(target, Nan::New("WITH_ASF").ToLocalChecked(), Nan::False()); #endif #ifdef TAGLIB_WITH_MP4 - target->Set(Nan::New("WITH_MP4").ToLocalChecked(), Nan::True()); + Nan::Set(target, Nan::New("WITH_MP4").ToLocalChecked(), Nan::True()); #else - target->Set(Nan::New("WITH_MP4").ToLocalChecked(), Nan::False()); + Nan::Set(target, Nan::New("WITH_MP4").ToLocalChecked(), Nan::False()); #endif - NODE_SET_METHOD(target, "read", AsyncReadFile); + Nan::SetMethod(target, "read", AsyncReadFile); #ifdef ENABLE_RESOLVERS - NODE_SET_METHOD(target, "addResolvers", AddResolvers); + Nan::SetMethod(target, "addResolvers", AddResolvers); #endif Tag::Init(target); } diff --git a/src/taglib.h b/src/taglib.h index 1a3501e..1fc523a 100644 --- a/src/taglib.h +++ b/src/taglib.h @@ -25,7 +25,7 @@ TagLib::File *createFile(TagLib::IOStream *stream, TagLib::String format); v8::Local ErrorToString(int error); v8::Local TagLibStringToString( TagLib::String s ); TagLib::String NodeStringToTagLibString( v8::Local s ); -void AsyncReadFile(const v8::FunctionCallbackInfo< v8::Value > &args); +void AsyncReadFile(const Nan::FunctionCallbackInfo< v8::Value > &args); void AsyncReadFileDo(uv_work_t *req); void AsyncReadFileAfter(uv_work_t *req); @@ -45,7 +45,7 @@ struct AsyncBaton { Tag *tag; /* only used by taglib.tag */ }; -void AddResolvers(const v8::FunctionCallbackInfo< v8::Value >& args); +void AddResolvers(const Nan::FunctionCallbackInfo< v8::Value >& args); class CallbackResolver; From 99d1ab00af66e9e2d4b625482345a7f41cbcbc7d Mon Sep 17 00:00:00 2001 From: Benjamin Schmitz Date: Thu, 24 Mar 2016 11:14:40 +0100 Subject: [PATCH 5/5] properly dispose of callback --- src/tag.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tag.cc b/src/tag.cc index d1449e0..3240346 100644 --- a/src/tag.cc +++ b/src/tag.cc @@ -165,7 +165,7 @@ void Tag::AsyncSaveTagAfter(uv_work_t *req) { Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->Global(), 1, argv); } - //baton->callback.Dispose(); + baton->callback.Reset(); delete baton; } @@ -289,7 +289,7 @@ void Tag::AsyncTagReadAfter(uv_work_t *req) { Nan::Call(Nan::New(baton->callback), Nan::GetCurrentContext()->Global(), 2, argv); } - //baton->callback.Dispose(); + baton->callback.Reset(); delete baton->path; delete baton; }