From eafb4b492c4ba6edea8861dbe94eb8217b16a57e Mon Sep 17 00:00:00 2001 From: erulabs Date: Mon, 28 Sep 2015 12:22:30 -0700 Subject: [PATCH 1/3] node 4x retry --- .travis.yml | 24 +++++------ node-stringprep.cc | 102 ++++++++++++++++++++++----------------------- package.json | 12 +++--- 3 files changed, 69 insertions(+), 69 deletions(-) diff --git a/.travis.yml b/.travis.yml index c6180b6..8fedc97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,14 @@ language: node_js node_js: - - "0.8" - - "0.10" - - "0.11" - - iojs -before_install: - - "sudo apt-get install libicu-dev" - # Workaround for a permissions issue with Travis virtual machine images - # that breaks Python's multiprocessing: - # https://github.com/travis-ci/travis-cookbooks/issues/155 - - sudo rm -rf /dev/shm - - sudo ln -s /run/shm /dev/shm - - npm i -g npm@1.X + - "4.1.1" +sudo: false +env: + - CXX="g++-4.8" +addons: + apt: + packages: + - libicu-dev + - g++-4.8 + - gcc-4.8 + sources: + - ubuntu-toolchain-r-test diff --git a/node-stringprep.cc b/node-stringprep.cc index 4b5b371..35ef152 100644 --- a/node-stringprep.cc +++ b/node-stringprep.cc @@ -15,17 +15,17 @@ class UnknownProfileException : public std::exception { // protect constructor from GC static Persistent stringprep_constructor; -class StringPrep : public ObjectWrap { +class StringPrep : public Nan::ObjectWrap { public: static void Initialize(Handle target) { - NanScope(); - Local t = NanNew(New); - NanAssignPersistent(stringprep_constructor, t); + Nan::HandleScope scope; + Local t = Nan::New(New); + //stringprep_constructor.Reset( t); t->InstanceTemplate()->SetInternalFieldCount(1); - NODE_SET_PROTOTYPE_METHOD(t, "prepare", Prepare); + Nan::SetPrototypeMethod(t, "prepare", Prepare); - target->Set(NanNew("StringPrep"), t->GetFunction()); + target->Set(Nan::New("StringPrep").ToLocalChecked(), t->GetFunction()); } bool good() const @@ -43,11 +43,11 @@ class StringPrep : public ObjectWrap { static NAN_METHOD(New) { - NanScope(); + Nan::HandleScope scope; - if (args.Length() >= 1 && args[0]->IsString()) + if (info.Length() >= 1 && info[0]->IsString()) { - String::Utf8Value arg0(args[0]->ToString()); + String::Utf8Value arg0(info[0]->ToString()); UStringPrepProfileType profileType; try { @@ -55,27 +55,27 @@ class StringPrep : public ObjectWrap { } catch (UnknownProfileException &) { - NanThrowTypeError("Unknown StringPrep profile"); - NanReturnUndefined(); + Nan::ThrowTypeError("Unknown StringPrep profile"); + return; } StringPrep *self = new StringPrep(profileType); if (self->good()) { - self->Wrap(args.This()); - NanReturnValue(args.This()); + self->Wrap(info.This()); + info.GetReturnValue().Set(info.This()); } else { const char* err = self->errorName(); delete self; - NanThrowError(err); - NanReturnUndefined(); + Nan::ThrowError(err); + return; } } else { - NanThrowTypeError("Bad argument."); - NanReturnUndefined(); + Nan::ThrowTypeError("Bad argument."); + return; } } @@ -97,17 +97,17 @@ class StringPrep : public ObjectWrap { static NAN_METHOD(Prepare) { - NanScope(); + Nan::HandleScope scope; - if (args.Length() >= 1 && args[0]->IsString()) + if (info.Length() >= 1 && info[0]->IsString()) { - StringPrep *self = ObjectWrap::Unwrap(args.This()); - String::Value arg0(args[0]->ToString()); - NanReturnValue(self->prepare(arg0)); + StringPrep *self = Nan::ObjectWrap::Unwrap(info.This()); + String::Value arg0(info[0]->ToString()); + info.GetReturnValue().Set(self->prepare(arg0)); } else { - NanThrowTypeError("Bad argument."); - NanReturnUndefined(); + Nan::ThrowTypeError("Bad argument."); + return; } } @@ -135,14 +135,14 @@ class StringPrep : public ObjectWrap { { // other error, just bail out delete[] dest; - NanThrowError(errorName()); - return NanUndefined(); + Nan::ThrowError(errorName()); + return Nan::Undefined(); } else destLen = w; } - Local result = NanNew(dest, destLen); + Local result = Nan::New(dest, destLen).ToLocalChecked(); delete[] dest; return result; } @@ -192,12 +192,12 @@ class StringPrep : public ObjectWrap { NAN_METHOD(ToUnicode) { - NanScope(); + Nan::HandleScope scope; - if (args.Length() >= 2 && args[0]->IsString() && args[1]->IsInt32()) + if (info.Length() >= 2 && info[0]->IsString() && info[1]->IsInt32()) { - String::Value str(args[0]->ToString()); - int32_t options = args[1]->ToInt32()->Value(); + String::Value str(info[0]->ToString()); + int32_t options = info[1]->ToInt32()->Value(); // ASCII encoding (xn--*--*) should be longer than Unicode size_t destLen = str.length() + 1; @@ -210,7 +210,7 @@ NAN_METHOD(ToUnicode) dest, destLen, options, NULL, &error); - + if (error == U_BUFFER_OVERFLOW_ERROR) { // retry with a dest buffer twice as large @@ -222,31 +222,31 @@ NAN_METHOD(ToUnicode) { // other error, just bail out delete[] dest; - NanThrowError(u_errorName(error)); - NanReturnUndefined(); + Nan::ThrowError(u_errorName(error)); + return; } else destLen = w; } - Local result = NanNew(dest, destLen); + Local result = Nan::New(dest, destLen).ToLocalChecked(); delete[] dest; - NanReturnValue(result); + info.GetReturnValue().Set(result); } else { - NanThrowTypeError("Bad argument."); - NanReturnUndefined(); + Nan::ThrowTypeError("Bad argument."); + return; } } NAN_METHOD(ToASCII) { - NanScope(); + Nan::HandleScope scope; - if (args.Length() >= 2 && args[0]->IsString() && args[1]->IsInt32()) + if (info.Length() >= 2 && info[0]->IsString() && info[1]->IsInt32()) { - String::Value str(args[0]->ToString()); - int32_t options = args[1]->ToInt32()->Value(); + String::Value str(info[0]->ToString()); + int32_t options = info[1]->ToInt32()->Value(); // find out length first UErrorCode error = U_ZERO_ERROR; @@ -270,17 +270,17 @@ NAN_METHOD(ToASCII) { // other error, just bail out delete[] dest; - NanThrowError(u_errorName(error)); - NanReturnUndefined(); + Nan::ThrowError(u_errorName(error)); + return; } - Local result = NanNew(dest, destLen); + Local result = Nan::New(dest, destLen).ToLocalChecked(); delete[] dest; - NanReturnValue(result); + info.GetReturnValue().Set(result); } else { - NanThrowTypeError("Bad argument."); - NanReturnUndefined(); + Nan::ThrowTypeError("Bad argument."); + return; } } @@ -288,10 +288,10 @@ NAN_METHOD(ToASCII) extern "C" void init(Handle target) { - NanScope(); + Nan::HandleScope scope; StringPrep::Initialize(target); - NODE_SET_METHOD(target, "toUnicode", ToUnicode); - NODE_SET_METHOD(target, "toASCII", ToASCII); + Nan::SetMethod(target, "toUnicode", ToUnicode); + Nan::SetMethod(target, "toASCII", ToASCII); } NODE_MODULE(node_stringprep, init) diff --git a/package.json b/package.json index f2664e4..91676b2 100644 --- a/package.json +++ b/package.json @@ -13,16 +13,16 @@ }, "dependencies": { "bindings": "~1.2.1", - "debug": "~2.0.0", - "nan": "~1.8.4" + "debug": "~2.2.0", + "nan": "~2.0.9" }, "devDependencies": { "grunt": "~0.4.2", "grunt-cli": "^0.1.13", - "grunt-contrib-jshint": "~0.7.2", - "grunt-mocha-cli": "~1.3.0", - "proxyquire": "~0.5.2", - "should": "~2.1.1" + "grunt-contrib-jshint": "~0.11.3", + "grunt-mocha-cli": "~1.14.0", + "proxyquire": "~1.7.2", + "should": "~7.1.0" }, "repository": { "type": "git", From 5cb40dd31432d70b68a9991914739f6421332a46 Mon Sep 17 00:00:00 2001 From: erulabs Date: Mon, 28 Sep 2015 16:57:35 -0700 Subject: [PATCH 2/3] all tests pass except leak --- index.js | 2 +- node-stringprep.cc | 31 +++++++++++++++++-------------- package.json | 1 + 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/index.js b/index.js index c40657a..324ac01 100644 --- a/index.js +++ b/index.js @@ -7,7 +7,7 @@ var UIDNA_ALLOW_UNASSIGNED = 1 var UIDNA_USE_STD3_RULES = 2 try { - var bindings = require('bindings')('node_stringprep.node') + var bindings = require('./node_modules/bindings/bindings.js')('node_stringprep.node') } catch (ex) { log( 'Cannot load StringPrep-' + diff --git a/node-stringprep.cc b/node-stringprep.cc index 35ef152..b534246 100644 --- a/node-stringprep.cc +++ b/node-stringprep.cc @@ -101,9 +101,10 @@ class StringPrep : public Nan::ObjectWrap { if (info.Length() >= 1 && info[0]->IsString()) { - StringPrep *self = Nan::ObjectWrap::Unwrap(info.This()); + StringPrep *self = ObjectWrap::Unwrap(info.This()); String::Value arg0(info[0]->ToString()); info.GetReturnValue().Set(self->prepare(arg0)); + return; } else { Nan::ThrowTypeError("Bad argument."); @@ -117,7 +118,7 @@ class StringPrep : public Nan::ObjectWrap { UChar *dest = NULL; while(!dest) { - error = U_ZERO_ERROR; + UErrorCode error = U_ZERO_ERROR; dest = new UChar[destLen]; size_t w = usprep_prepare(profile, *str, str.length(), @@ -131,20 +132,21 @@ class StringPrep : public Nan::ObjectWrap { delete[] dest; dest = NULL; } - else if (!good()) + else if (U_FAILURE(error)) { // other error, just bail out delete[] dest; - Nan::ThrowError(errorName()); + Nan::ThrowTypeError("Bad argument."); return Nan::Undefined(); } else destLen = w; } - Local result = Nan::New(dest, destLen).ToLocalChecked(); + Nan::ThrowTypeError("Bad argument."); + delete[] dest; - return result; + return Nan::New(dest, destLen).ToLocalChecked(); } private: @@ -286,12 +288,13 @@ NAN_METHOD(ToASCII) /*** Initialization ***/ -extern "C" void init(Handle target) -{ - Nan::HandleScope scope; - StringPrep::Initialize(target); - Nan::SetMethod(target, "toUnicode", ToUnicode); - Nan::SetMethod(target, "toASCII", ToASCII); +extern "C" { + static void init (Handle target) + { + Nan::HandleScope scope; + StringPrep::Initialize(target); + Nan::SetMethod(target, "toUnicode", ToUnicode); + Nan::SetMethod(target, "toASCII", ToASCII); + } + NODE_MODULE(node_stringprep, init) } - -NODE_MODULE(node_stringprep, init) diff --git a/package.json b/package.json index 91676b2..6d4899b 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dependencies": { "bindings": "~1.2.1", "debug": "~2.2.0", + "iconv-lite": "^0.4.12", "nan": "~2.0.9" }, "devDependencies": { From c6a71670b8ab5c5168eb60307b64af35266773e7 Mon Sep 17 00:00:00 2001 From: erulabs Date: Mon, 28 Sep 2015 18:29:17 -0700 Subject: [PATCH 3/3] very very close. Missing something on error handeling for unknown profiles --- node-stringprep.cc | 9 +++------ test/fallback.js | 14 +++++++------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/node-stringprep.cc b/node-stringprep.cc index b534246..6f6dc0b 100644 --- a/node-stringprep.cc +++ b/node-stringprep.cc @@ -101,10 +101,9 @@ class StringPrep : public Nan::ObjectWrap { if (info.Length() >= 1 && info[0]->IsString()) { - StringPrep *self = ObjectWrap::Unwrap(info.This()); + StringPrep *self = Nan::ObjectWrap::Unwrap(info.This()); String::Value arg0(info[0]->ToString()); info.GetReturnValue().Set(self->prepare(arg0)); - return; } else { Nan::ThrowTypeError("Bad argument."); @@ -132,19 +131,17 @@ class StringPrep : public Nan::ObjectWrap { delete[] dest; dest = NULL; } - else if (U_FAILURE(error)) + else if (!U_SUCCESS(error)) { // other error, just bail out delete[] dest; - Nan::ThrowTypeError("Bad argument."); + Nan::ThrowError(u_errorName(error)); return Nan::Undefined(); } else destLen = w; } - Nan::ThrowTypeError("Bad argument."); - delete[] dest; return Nan::New(dest, destLen).ToLocalChecked(); } diff --git a/test/fallback.js b/test/fallback.js index e633c1b..0988775 100644 --- a/test/fallback.js +++ b/test/fallback.js @@ -11,7 +11,7 @@ describe('Should use JS fallbacks for StringPrep', function() { var prep = new StringPrep('cRaZYcASE') try { prep.prepare('UPPERCASE') - done('Should have thrown error') + done(new Error('Should have thrown error')) } catch (e) { e.message.should.equal(prep.UNKNOWN_PROFILE_TYPE) done() @@ -58,7 +58,7 @@ describe('Should use JS fallbacks for StringPrep', function() { try { prep.prepare('UPPERCASE') isDone = true - done('Should have thrown error') + done(new Error('Should have thrown error for profile ' + profile)) } catch (e) { e.message.should.equal(prep.UNHANDLED_FALLBACK) } @@ -69,7 +69,7 @@ describe('Should use JS fallbacks for StringPrep', function() { }) describe('Can disable fallbacks', function() { - + var StringPrep = proxyquire('../index', { 'bindings': null }).StringPrep it('Should allow javascript fallbacks to be disabled', function(done) { @@ -77,19 +77,19 @@ describe('Can disable fallbacks', function() { try { prep.disableJsFallbacks() prep.prepare('UPPERCASE') - done('Should have thrown exception') + done(new Error('Should have thrown exception')) } catch (e) { e.message.should.equal(prep.LIBICU_NOT_AVAILABLE) done() } }) - + it('Should allow javascript fallbacks to be re-enabled', function(done) { var prep = new StringPrep('nameprep') try { prep.disableJsFallbacks() prep.prepare('UPPERCASE') - done('Should have thrown exception') + done(new Error('Should have thrown exception')) } catch (e) { e.message.should.equal(prep.LIBICU_NOT_AVAILABLE) prep.enableJsFallbacks() @@ -97,7 +97,7 @@ describe('Can disable fallbacks', function() { done() } }) - + }) describe('\'isNative\' method test', function() {