From 87e37411493bb98331c60033705462a2cb8b1dfd Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 28 Jun 2016 09:37:09 -0700 Subject: [PATCH 1/2] deps: update icu-small to include punycode datafiles --- deps/icu-small/source/data/in/icudt57l.dat | Bin 1873824 -> 1933056 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/deps/icu-small/source/data/in/icudt57l.dat b/deps/icu-small/source/data/in/icudt57l.dat index e2e8caab68322b4e1d475d0a7df28a18962110da..87131f44e10ac40aaedc96158dffe7a84df9be08 100644 GIT binary patch delta 24820 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%0DDcmu5&a zrG5NNX_nN3FOp_UbELUaPrhDYo-|)tAT5-NrA5+W=>=(-^rEy!l6S zMrpHDDs7RrO1JT4(l+Tm>3!(~X}5F-|Dm)`Iv{-{eJp(<9hE+n66o~mGwE~b3+YSg zwDgU1R{CD*%b$~emVS|blUfT&sa(pEjj~y`%61u-Ntu>iG9!ECZvuWfAPaI>j>(c7 zmut&)<@$0%xj#RLYb-aFo6A?pt>s)fPi`ZB&9{~FruL`6|*DRq_lN<*cw(o|`#T&1*Du2I@3 z1EuSgcFGOPjY=owCgolJlkTOJ>#owh2Q-&)elu^ok z%2?$=WrC7WCMi>tY07lvQROk^ab>phl%gsV15YdeRGv|uRi0D+r7*(t$_vUer2u7+2!8;`N34Lfv@%c%yiec(Ztmc*}U}cy2r|-cYzMeto=M{D%0A@lNqB@viY( z;yvS1!r3cc&v|>iPrP6JAMqB>f!a4pYAx{Z;>%4?DSDP61uC1(aVq%+y*)8Fo(ZX< zSH^>X=aZ@cOP3fN*T44=$HDP8V%6sP#2=VoFI5Kl>vDI}FD-pJ3Yz#!c9zoXJlV-| zb@BoFrji2(Xroab^)X#!i5Tt$D9JudugESbJworzE{PnchnceL8A@iJq}P&ahaYK9 z9sVPITgjdu>9tOE&egQDWP#ObH>xA9qg$4o#GGTY=eDDjk~;0^@!9IC8|c#|3p>!W fvr6W;oa3`i%i;Gh)!zrf4}pacD53guMNR(?N$)u{ delta 458 zcmWm6y)Q#i7{~G7ZF}prx3{;&RU~3zk<`HCZIy@+CJfg=Ow}}z7%FX$RASJ?AQHo6 zM?=J7keG-8e*uF;gy?7?z8${jbIy||r|`GxpJhvhe7B@QgTs_&(Zdyd#2p+BOUHOq z4(b|HKlOS-Ki!~r^nN1>1=z@+M5qvkAmSXi{QhTe&#ZM2^)9byK{0p(TUa>t92KkYBS#0Qu7obp!w0mN68gXl z8X@Tg<5>Pqs4q0c2XR;93{nfOma&8z)rE6c``G#J>J Date: Tue, 21 Jun 2016 14:03:05 -0700 Subject: [PATCH 2/2] net: use icu's punycode implementation ICU has a punycode implementation built in. Use it instead of the javascript implementation because it's much faster. --- benchmark/net/punycode.js | 75 ++++++++++++++++ lib/url.js | 12 ++- src/node_i18n.cc | 132 +++++++++++++++++++++++++++++ test/parallel/test-icu-punycode.js | 72 ++++++++++++++++ tools/icu/icu-generic.gyp | 9 +- tools/icu/icu_small.json | 3 +- 6 files changed, 291 insertions(+), 12 deletions(-) create mode 100644 benchmark/net/punycode.js create mode 100644 test/parallel/test-icu-punycode.js diff --git a/benchmark/net/punycode.js b/benchmark/net/punycode.js new file mode 100644 index 00000000000000..f4d22557ac5d65 --- /dev/null +++ b/benchmark/net/punycode.js @@ -0,0 +1,75 @@ +'use strict'; + +const common = require('../common.js'); +const icu = process.binding('icu'); +const punycode = require('punycode'); + +const bench = common.createBenchmark(main, { + method: ['punycode', 'icu'], + n: [1024], + val: [ + 'افغانستا.icom.museum', + 'الجزائر.icom.museum', + 'österreich.icom.museum', + 'বাংলাদেশ.icom.museum', + 'беларусь.icom.museum', + 'belgië.icom.museum', + 'българия.icom.museum', + 'تشادر.icom.museum', + '中国.icom.museum', + 'القمر.icom.museum', + 'κυπρος.icom.museum', + 'českárepublika.icom.museum', + 'مصر.icom.museum', + 'ελλάδα.icom.museum', + 'magyarország.icom.museum', + 'ísland.icom.museum', + 'भारत.icom.museum', + 'ايران.icom.museum', + 'éire.icom.museum', + 'איקו״ם.ישראל.museum', + '日本.icom.museum', + 'الأردن.icom.museum' + ] +}); + +function usingPunycode(val) { + punycode.toUnicode(punycode.toASCII(val)); +} + +function usingICU(val) { + icu.toUnicode(icu.toASCII(val)); +} + +function runPunycode(n, val) { + common.v8ForceOptimization(usingPunycode, val); + var i = 0; + bench.start(); + for (; i < n; i++) + usingPunycode(val); + bench.end(n); +} + +function runICU(n, val) { + common.v8ForceOptimization(usingICU, val); + var i = 0; + bench.start(); + for (; i < n; i++) + usingICU(val); + bench.end(n); +} + +function main(conf) { + const n = +conf.n; + const val = conf.val; + switch (conf.method) { + case 'punycode': + runPunycode(n, val); + break; + case 'icu': + runICU(n, val); + break; + default: + throw new Error('Unexpected method'); + } +} diff --git a/lib/url.js b/lib/url.js index f072b33c86975c..94fecc94270431 100644 --- a/lib/url.js +++ b/lib/url.js @@ -1,6 +1,14 @@ 'use strict'; -const punycode = require('punycode'); +function importPunycode() { + try { + return process.binding('icu'); + } catch (e) { + return require('punycode'); + } +} + +const { toASCII } = importPunycode(); exports.parse = urlParse; exports.resolve = urlResolve; @@ -309,7 +317,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { // It only converts parts of the domain name that // have non-ASCII characters, i.e. it doesn't matter if // you call it with a domain that already is ASCII-only. - this.hostname = punycode.toASCII(this.hostname); + this.hostname = toASCII(this.hostname); } var p = this.port ? ':' + this.port : ''; diff --git a/src/node_i18n.cc b/src/node_i18n.cc index 3e5b3a91298988..0f3b9b76e6959e 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -23,8 +23,16 @@ #if defined(NODE_HAVE_I18N_SUPPORT) +#include "node.h" +#include "env.h" +#include "env-inl.h" +#include "util.h" +#include "util-inl.h" +#include "v8.h" + #include #include +#include #ifdef NODE_HAVE_SMALL_ICU /* if this is defined, we have a 'secondary' entry point. @@ -43,6 +51,13 @@ extern "C" const char U_DATA_API SMALL_ICUDATA_ENTRY_POINT[]; namespace node { +using v8::Context; +using v8::FunctionCallbackInfo; +using v8::Local; +using v8::Object; +using v8::String; +using v8::Value; + bool flag_icu_data_dir = false; namespace i18n { @@ -64,7 +79,124 @@ bool InitializeICUDirectory(const char* icu_data_path) { } } +static int32_t ToUnicode(MaybeStackBuffer* buf, + const char* input, + size_t length) { + UErrorCode status = U_ZERO_ERROR; + uint32_t options = UIDNA_DEFAULT; + options |= UIDNA_NONTRANSITIONAL_TO_UNICODE; + UIDNA* uidna = uidna_openUTS46(options, &status); + if (U_FAILURE(status)) + return -1; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + + int32_t len = uidna_nameToUnicodeUTF8(uidna, + input, length, + **buf, buf->length(), + &info, + &status); + + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + buf->AllocateSufficientStorage(len); + len = uidna_nameToUnicodeUTF8(uidna, + input, length, + **buf, buf->length(), + &info, + &status); + } + + if (U_FAILURE(status)) + len = -1; + + uidna_close(uidna); + return len; +} + +static int32_t ToASCII(MaybeStackBuffer* buf, + const char* input, + size_t length) { + UErrorCode status = U_ZERO_ERROR; + uint32_t options = UIDNA_DEFAULT; + options |= UIDNA_NONTRANSITIONAL_TO_ASCII; + UIDNA* uidna = uidna_openUTS46(options, &status); + if (U_FAILURE(status)) + return -1; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + + int32_t len = uidna_nameToASCII_UTF8(uidna, + input, length, + **buf, buf->length(), + &info, + &status); + + if (status == U_BUFFER_OVERFLOW_ERROR) { + status = U_ZERO_ERROR; + buf->AllocateSufficientStorage(len); + len = uidna_nameToASCII_UTF8(uidna, + input, length, + **buf, buf->length(), + &info, + &status); + } + + if (U_FAILURE(status)) + len = -1; + + uidna_close(uidna); + return len; +} + +static void ToUnicode(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + CHECK_GE(args.Length(), 1); + CHECK(args[0]->IsString()); + Utf8Value val(env->isolate(), args[0]); + MaybeStackBuffer buf; + int32_t len = ToUnicode(&buf, *val, val.length()); + + if (len < 0) { + return env->ThrowError("Cannot convert name to Unicode"); + } + + args.GetReturnValue().Set( + String::NewFromUtf8(env->isolate(), + *buf, + v8::NewStringType::kNormal, + len).ToLocalChecked()); +} + +static void ToASCII(const FunctionCallbackInfo& args) { + Environment* env = Environment::GetCurrent(args); + CHECK_GE(args.Length(), 1); + CHECK(args[0]->IsString()); + Utf8Value val(env->isolate(), args[0]); + MaybeStackBuffer buf; + int32_t len = ToASCII(&buf, *val, val.length()); + + if (len < 0) { + return env->ThrowError("Cannot convert name to ASCII"); + } + + args.GetReturnValue().Set( + String::NewFromUtf8(env->isolate(), + *buf, + v8::NewStringType::kNormal, + len).ToLocalChecked()); +} + +void Init(Local target, + Local unused, + Local context, + void* priv) { + Environment* env = Environment::GetCurrent(context); + env->SetMethod(target, "toUnicode", ToUnicode); + env->SetMethod(target, "toASCII", ToASCII); +} + } // namespace i18n } // namespace node +NODE_MODULE_CONTEXT_AWARE_BUILTIN(icu, node::i18n::Init) + #endif // NODE_HAVE_I18N_SUPPORT diff --git a/test/parallel/test-icu-punycode.js b/test/parallel/test-icu-punycode.js new file mode 100644 index 00000000000000..d9b36e7df78882 --- /dev/null +++ b/test/parallel/test-icu-punycode.js @@ -0,0 +1,72 @@ +'use strict'; + +const common = require('../common'); +const icu = getPunycode(); +const assert = require('assert'); + +function getPunycode() { + try { + return process.binding('icu'); + } catch (err) { + return undefined; + } +} + +if (!icu) { + common.skip('icu punycode tests because ICU is not present.'); + return; +} + +// Credit for list: http://www.i18nguy.com/markup/idna-examples.html +const tests = [ + 'افغانستا.icom.museum', + 'الجزائر.icom.museum', + 'österreich.icom.museum', + 'বাংলাদেশ.icom.museum', + 'беларусь.icom.museum', + 'belgië.icom.museum', + 'българия.icom.museum', + 'تشادر.icom.museum', + '中国.icom.museum', + 'القمر.icom.museum', + 'κυπρος.icom.museum', + 'českárepublika.icom.museum', + 'مصر.icom.museum', + 'ελλάδα.icom.museum', + 'magyarország.icom.museum', + 'ísland.icom.museum', + 'भारत.icom.museum', + 'ايران.icom.museum', + 'éire.icom.museum', + 'איקו״ם.ישראל.museum', + '日本.icom.museum', + 'الأردن.icom.museum', + 'қазақстан.icom.museum', + '한국.icom.museum', + 'кыргызстан.icom.museum', + 'ລາວ.icom.museum', + 'لبنان.icom.museum', + 'македонија.icom.museum', + 'موريتانيا.icom.museum', + 'méxico.icom.museum', + 'монголулс.icom.museum', + 'المغرب.icom.museum', + 'नेपाल.icom.museum', + 'عمان.icom.museum', + 'قطر.icom.museum', + 'românia.icom.museum', + 'россия.иком.museum', + 'србијаицрнагора.иком.museum', + 'இலங்கை.icom.museum', + 'españa.icom.museum', + 'ไทย.icom.museum', + 'تونس.icom.museum', + 'türkiye.icom.museum', + 'украина.icom.museum', + 'việtnam.icom.museum' +]; + +// Testing the roundtrip +tests.forEach((i) => { + assert.strictEqual(i, icu.toUnicode(icu.toASCII(i))); +}); diff --git a/tools/icu/icu-generic.gyp b/tools/icu/icu-generic.gyp index a61b294141fc21..9d466ac39227c3 100644 --- a/tools/icu/icu-generic.gyp +++ b/tools/icu/icu-generic.gyp @@ -37,8 +37,7 @@ 'defines': [ # ICU cannot swap the initial data without this. # http://bugs.icu-project.org/trac/ticket/11046 - 'UCONFIG_NO_LEGACY_CONVERSION=1', - 'UCONFIG_NO_IDNA=1', + 'UCONFIG_NO_LEGACY_CONVERSION=1' ], }], ], @@ -428,9 +427,6 @@ #'<(icu_path)/source/common/ubidi_props_data.h', # and the callers '<(icu_path)/source/common/ushape.cpp', - '<(icu_path)/source/common/usprep.cpp', - '<(icu_path)/source/common/uts46.cpp', - '<(icu_path)/source/common/uidna.cpp', ]}], [ 'icu_ver_major == 57', { 'sources!': [ # work around http://bugs.icu-project.org/trac/ticket/12451 @@ -447,9 +443,6 @@ #'<(icu_path)/source/common/ubidi_props_data.h', # and the callers '<(icu_path)/source/common/ushape.cpp', - '<(icu_path)/source/common/usprep.cpp', - '<(icu_path)/source/common/uts46.cpp', - '<(icu_path)/source/common/uidna.cpp', ]}], [ 'OS == "solaris"', { 'defines': [ '_XOPEN_SOURCE_EXTENDED=0', diff --git a/tools/icu/icu_small.json b/tools/icu/icu_small.json index e434794e91c16b..de26e2cbb14b16 100644 --- a/tools/icu/icu_small.json +++ b/tools/icu/icu_small.json @@ -24,7 +24,7 @@ "region": "none", "zone": "locales", "converters": "none", - "stringprep": "none", + "stringprep": "locales", "translit": "none", "brkfiles": "none", "brkdict": "none", @@ -34,7 +34,6 @@ "remove": [ "cnvalias.icu", "postalCodeData.res", - "uts46.nrm", "genderList.res", "brkitr/root.res", "unames.icu"