JS: libphonenumber v5.2
authorroubert@google.com <roubert@google.com@ee073f10-1060-11df-b6a4-87a95322a99c>
Tue, 6 Nov 2012 16:04:51 +0000 (16:04 +0000)
committerroubert@google.com <roubert@google.com@ee073f10-1060-11df-b6a4-87a95322a99c>
Tue, 6 Nov 2012 16:04:51 +0000 (16:04 +0000)
Review URL: https://codereview.appspot.com/6821053

git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@538 ee073f10-1060-11df-b6a4-87a95322a99c

javascript/README
javascript/i18n/phonenumbers/metadata.js
javascript/i18n/phonenumbers/metadatafortesting.js
javascript/i18n/phonenumbers/metadatalite.js
javascript/i18n/phonenumbers/phonenumberutil.js
javascript/i18n/phonenumbers/phonenumberutil_test.js

index b2a4271..e40da42 100644 (file)
@@ -25,7 +25,7 @@ pages with your web browser:
 
 How to update:
 ==============
-The JavaScript library is ported from the Java implementation (revision 524).
+The JavaScript library is ported from the Java implementation (revision 536).
 When the Java project gets updated follow these steps to update the JavaScript
 project:
 
index 8e3398b..d97f988 100644 (file)
@@ -185,7 +185,7 @@ i18n.phonenumbers.metadata.countryCodeToRegionCodeMap = {
 ,596:["MQ"]
 ,597:["SR"]
 ,598:["UY"]
-,599:["CW","AN","BQ"]
+,599:["CW","BQ"]
 ,670:["TL"]
 ,672:["NF"]
 ,673:["BN"]
@@ -399,20 +399,6 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,,[,,"10[123]","\\d{3}",,,"102"]
 ,[,,"NA","NA"]
 ]
-,"AN":[,[,,"5\\d{6}","\\d{7}"]
-,[,,"5(?:4[2-8]|8[239])\\d{4}","\\d{7}",,,"5451234"]
-,[,,"5(?:1[02]|2\\d|5[0-79]|8[016-8])\\d{4}","\\d{7}",,,"5101234"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,"AN",599,"00",,,,,,,,,,[,,"NA","NA"]
-,,,[,,"NA","NA"]
-,[,,"NA","NA"]
-,,[,,"112|911","\\d{3}",,,"112"]
-,[,,"NA","NA"]
-]
 ,"AO":[,[,,"[29]\\d{8}","\\d{9}"]
 ,[,,"2\\d(?:[26-9]\\d|\\d[26-9])\\d{5}","\\d{9}",,,"222123456"]
 ,[,,"9[1-4]\\d{7}","\\d{9}",,,"923123456"]
@@ -1369,13 +1355,13 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"180\\d{5,11}","\\d{8,14}",,,"18012345"]
 ,[,,"700\\d{8}","\\d{11}",,,"70012345678"]
 ,[,,"NA","NA"]
-,"DE",49,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{4,11})","$1/$2",["3[02]|40|[68]9"]
+,"DE",49,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{4,11})","$1 $2",["3[02]|40|[68]9"]
 ,"0$1","",0]
-,[,"(\\d{3})(\\d{3,11})","$1/$2",["2(?:\\d1|0[2389]|1[24]|28|34)|3(?:[3-9][15]|40)|[4-8][1-9]1|9(?:06|[1-9]1)"]
+,[,"(\\d{3})(\\d{3,11})","$1 $2",["2(?:\\d1|0[2389]|1[24]|28|34)|3(?:[3-9][15]|40)|[4-8][1-9]1|9(?:06|[1-9]1)"]
 ,"0$1","",0]
-,[,"(\\d{4})(\\d{2,11})","$1/$2",["[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:[3569][02-46-9]|4[2-4679]|7[2-467]|8[2-46-8])","[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:3(?:0[1-467]|2[127-9]|3[124578]|[46][1246]|7[1257-9]|8[1256]|9[145])|4(?:2[135]|3[1357]|4[13578]|6[1246]|7[1356]|9[1346])|5(?:0[14]|2[1-3589]|3[1357]|4[1246]|6[1-4]|7[1346]|8[13568]|9[1246])|6(?:0[356]|2[1-489]|3[124-6]|4[1347]|6[13]|7[12579]|8[1-356]|9[135])|7(?:2[1-7]|3[1357]|4[145]|6[1-5]|7[1-4])|8(?:21|3[1468]|4[1347]|6[0135-9]|7[1467]|8[136])|9(?:0[12479]|2[1358]|3[1357]|4[134679]|6[1-9]|7[136]|8[147]|9[1468]))"]
+,[,"(\\d{4})(\\d{2,11})","$1 $2",["[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:[3569][02-46-9]|4[2-4679]|7[2-467]|8[2-46-8])","[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:3(?:0[1-467]|2[127-9]|3[124578]|[46][1246]|7[1257-9]|8[1256]|9[145])|4(?:2[135]|3[1357]|4[13578]|6[1246]|7[1356]|9[1346])|5(?:0[14]|2[1-3589]|3[1357]|4[1246]|6[1-4]|7[1346]|8[13568]|9[1246])|6(?:0[356]|2[1-489]|3[124-6]|4[1347]|6[13]|7[12579]|8[1-356]|9[135])|7(?:2[1-7]|3[1357]|4[145]|6[1-5]|7[1-4])|8(?:21|3[1468]|4[1347]|6[0135-9]|7[1467]|8[136])|9(?:0[12479]|2[1358]|3[1357]|4[134679]|6[1-9]|7[136]|8[147]|9[1468]))"]
 ,"0$1","",0]
-,[,"(\\d{5})(\\d{1,10})","$1/$2",["3"]
+,[,"(\\d{5})(\\d{1,10})","$1 $2",["3"]
 ,"0$1","",0]
 ,[,"(1\\d{2})(\\d{7,8})","$1 $2",["1[5-7]"]
 ,"0$1","",0]
@@ -1945,7 +1931,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"NA","NA"]
 ]
 ,"GR":[,[,,"[26-9]\\d{9}","\\d{10}"]
-,[,,"2(?:1\\d{2}|2(?:3[1-8]|4[1-7]|5[1-4]|6[1-8]|7[1-5]|[289][1-9])|3(?:1\\d|2[1-5]|3[1-4]|[45][1-3]|7[1-7]|8[1-6]|9[1-79])|4(?:1\\d|2[1-8]|3[1-4]|4[13-5]|6[1-578]|9[1-5])|5(?:1\\d|2[1-3]|4[124]|5[1-6]|[39][1-4])|6(?:1\\d|3[124]|4[1-7]|5[13-9]|[269][1-6]|7[14]|8[1-5])|7(?:1\\d|2[1-5]|3[1-6]|4[1-7]|5[1-57]|6[134]|9[15-7])|8(?:1\\d|2[1-5]|[34][1-4]|9[1-7]))\\d{6}","\\d{10}",,,"2123456789"]
+,[,,"2(?:1\\d{2}|2(?:3[1-8]|4[1-7]|5[1-4]|6[1-8]|7[1-5]|[289][1-9])|3(?:1\\d|2[1-57]|3[1-4]|[45][1-3]|7[1-7]|8[1-6]|9[1-79])|4(?:1\\d|2[1-8]|3[1-4]|4[13-5]|6[1-578]|9[1-5])|5(?:1\\d|2[1-3]|4[124]|5[1-6]|[39][1-4])|6(?:1\\d|3[124]|4[1-7]|5[13-9]|[269][1-6]|7[14]|8[1-5])|7(?:1\\d|2[1-5]|3[1-6]|4[1-7]|5[1-57]|6[134]|9[15-7])|8(?:1\\d|2[1-5]|[34][1-4]|9[1-7]))\\d{6}","\\d{10}",,,"2123456789"]
 ,[,,"69\\d{8}","\\d{10}",,,"6912345678"]
 ,[,,"800\\d{7}","\\d{10}",,,"8001234567"]
 ,[,,"90[19]\\d{7}","\\d{10}",,,"9091234567"]
@@ -2070,16 +2056,18 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"NA","NA"]
 ]
 ,"HR":[,[,,"[1-7]\\d{5,8}|[89]\\d{6,11}","\\d{6,12}"]
-,[,,"(?:1|6[029])\\d{7}|(?:2[0-3]|3[1-5]|4[02-47-9]|5[1-3])\\d{6}","\\d{6,9}",,,"12345678"]
+,[,,"1\\d{7}|(?:2[0-3]|3[1-5]|4[02-47-9]|5[1-3])\\d{6}","\\d{6,8}",,,"12345678"]
 ,[,,"9[1257-9]\\d{6,10}","\\d{8,12}",,,"912345678"]
 ,[,,"80[01]\\d{4,7}","\\d{7,10}",,,"8001234567"]
-,[,,"6[145]\\d{4,7}","\\d{6,9}",,,"611234"]
+,[,,"6(?:[09]\\d{7}|[145]\\d{4,7})","\\d{6,9}",,,"611234"]
 ,[,,"NA","NA"]
 ,[,,"7[45]\\d{4,7}","\\d{6,9}",,,"741234567"]
 ,[,,"NA","NA"]
 ,"HR",385,"00","0",,,"0",,,,[[,"(1)(\\d{4})(\\d{3})","$1 $2 $3",["1"]
 ,"0$1","",0]
-,[,"(6[029])(\\d{4})(\\d{3})","$1 $2 $3",["6[029]"]
+,[,"(6[09])(\\d{4})(\\d{3})","$1 $2 $3",["6[09]"]
+,"0$1","",0]
+,[,"(62)(\\d{3})(\\d{3,4})","$1 $2 $3",["62"]
 ,"0$1","",0]
 ,[,"([2-5]\\d)(\\d{3})(\\d{3})","$1 $2 $3",["[2-5]"]
 ,"0$1","",0]
@@ -2100,7 +2088,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ]
 ,,[,,"NA","NA"]
 ,,,[,,"NA","NA"]
-,[,,"NA","NA"]
+,[,,"62\\d{6,7}","\\d{8,9}",,,"62123456"]
 ,,[,,"1(?:12|92)|9[34]","\\d{2,3}",,,"112"]
 ,[,,"NA","NA"]
 ]
@@ -3613,9 +3601,9 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,,[,,"111","\\d{3}",,,"111"]
 ,[,,"NA","NA"]
 ]
-,"OM":[,[,,"(?:2[3-6]|5|9[2-9])\\d{6}|800\\d{5,6}","\\d{7,9}"]
-,[,,"2[3-6]\\d{6}","\\d{8}",,,"23123456"]
-,[,,"9[2-9]\\d{6}","\\d{8}",,,"92123456"]
+,"OM":[,[,,"(?:2[2-6]|5|9[1-9])\\d{6}|800\\d{5,6}","\\d{7,9}"]
+,[,,"2[2-6]\\d{6}","\\d{8}",,,"23123456"]
+,[,,"9[1-9]\\d{6}","\\d{8}",,,"92123456"]
 ,[,,"8007\\d{4,5}|500\\d{4}","\\d{7,9}",,,"80071234"]
 ,[,,"NA","NA"]
 ,[,,"NA","NA"]
@@ -4061,15 +4049,15 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,,[,,"99[7-9]","\\d{3}",,,"999"]
 ,[,,"NA","NA"]
 ]
-,"SB":[,[,,"[1-8]\\d{4,6}","\\d{5,7}"]
+,"SB":[,[,,"[1-9]\\d{4,6}","\\d{5,7}"]
 ,[,,"(?:1[4-79]|[23]\\d|4[01]|5[03]|6[0-37])\\d{3}","\\d{5}",,,"40123"]
-,[,,"48\\d{3}|7(?:4\\d|5[025-8]|6[0-6])\\d{4}|8[4-8]\\d{5}","\\d{5,7}",,,"7421234"]
+,[,,"48\\d{3}|7(?:[46-8]\\d|5[025-9]|90)\\d{4}|8[4-8]\\d{5}|9(?:[46]\\d|5[0-46-9]|7[0-689]|8[0-79]|9[0-8])\\d{4}","\\d{5,7}",,,"7421234"]
 ,[,,"1[38]\\d{3}","\\d{5}",,,"18123"]
 ,[,,"NA","NA"]
 ,[,,"NA","NA"]
 ,[,,"NA","NA"]
 ,[,,"5[12]\\d{3}","\\d{5}",,,"51123"]
-,"SB",677,"0[01]",,,,,,,,[[,"(\\d{3})(\\d{4})","$1 $2",["[78]"]
+,"SB",677,"0[01]",,,,,,,,[[,"(\\d{3})(\\d{4})","$1 $2",["[7-9]"]
 ,"","",0]
 ]
 ,,[,,"NA","NA"]
@@ -5027,7 +5015,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"(?:1[0-8]|2[1-478]|3[1-69]|4\\d|5[1346-8])\\d{7}","\\d{8,9}",,,"101234567"]
 ,[,,"(?:7[1-4689]|8[1-5789])\\d{3,7}","\\d{5,9}",,,"711234567"]
 ,[,,"80\\d{7}","\\d{9}",,,"801234567"]
-,[,,"86[1-9]\\d{6}","\\d{9}",,,"861234567"]
+,[,,"86[2-9]\\d{6}","\\d{9}",,,"862345678"]
 ,[,,"860\\d{6}","\\d{9}",,,"860123456"]
 ,[,,"NA","NA"]
 ,[,,"87\\d{7}","\\d{9}",,,"871234567"]
@@ -5042,7 +5030,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ]
 ,,[,,"NA","NA"]
 ,,,[,,"NA","NA"]
-,[,,"NA","NA"]
+,[,,"861\\d{6}","\\d{9}",,,"861123456"]
 ,,[,,"1(?:01(?:11|77)|12)","\\d{3,5}",,,"10111"]
 ,[,,"NA","NA"]
 ]
index eae240e..29c59d7 100644 (file)
@@ -488,7 +488,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,,[,,"NA","NA"]
 ,,,[,,"NA","NA"]
 ,[,,"NA","NA"]
-,,[,,"NA","NA"]
+,1,[,,"NA","NA"]
 ,[,,"NA","NA"]
 ]
 ,"979":[,[,,"\\d{9}","\\d{9}",,,"123456789"]
index 318422b..bb36de8 100644 (file)
@@ -185,7 +185,7 @@ i18n.phonenumbers.metadata.countryCodeToRegionCodeMap = {
 ,596:["MQ"]
 ,597:["SR"]
 ,598:["UY"]
-,599:["CW","AN","BQ"]
+,599:["CW","BQ"]
 ,670:["TL"]
 ,672:["NF"]
 ,673:["BN"]
@@ -399,20 +399,6 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,,[,,"10[123]","\\d{3}"]
 ,[,,"NA","NA"]
 ]
-,"AN":[,[,,"5\\d{6}","\\d{7}"]
-,[,,"5(?:4[2-8]|8[239])\\d{4}","\\d{7}"]
-,[,,"5(?:1[02]|2\\d|5[0-79]|8[016-8])\\d{4}","\\d{7}"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,[,,"NA","NA"]
-,"AN",599,"00",,,,,,,,,,[,,"NA","NA"]
-,,,[,,"NA","NA"]
-,[,,"NA","NA"]
-,,[,,"112|911","\\d{3}"]
-,[,,"NA","NA"]
-]
 ,"AO":[,[,,"[29]\\d{8}","\\d{9}"]
 ,[,,"2\\d(?:[26-9]\\d|\\d[26-9])\\d{5}","\\d{9}"]
 ,[,,"9[1-4]\\d{7}","\\d{9}"]
@@ -1369,13 +1355,13 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"180\\d{5,11}","\\d{8,14}"]
 ,[,,"700\\d{8}","\\d{11}"]
 ,[,,"NA","NA"]
-,"DE",49,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{4,11})","$1/$2",["3[02]|40|[68]9"]
+,"DE",49,"00","0",,,"0",,,,[[,"(\\d{2})(\\d{4,11})","$1 $2",["3[02]|40|[68]9"]
 ,"0$1","",0]
-,[,"(\\d{3})(\\d{3,11})","$1/$2",["2(?:\\d1|0[2389]|1[24]|28|34)|3(?:[3-9][15]|40)|[4-8][1-9]1|9(?:06|[1-9]1)"]
+,[,"(\\d{3})(\\d{3,11})","$1 $2",["2(?:\\d1|0[2389]|1[24]|28|34)|3(?:[3-9][15]|40)|[4-8][1-9]1|9(?:06|[1-9]1)"]
 ,"0$1","",0]
-,[,"(\\d{4})(\\d{2,11})","$1/$2",["[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:[3569][02-46-9]|4[2-4679]|7[2-467]|8[2-46-8])","[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:3(?:0[1-467]|2[127-9]|3[124578]|[46][1246]|7[1257-9]|8[1256]|9[145])|4(?:2[135]|3[1357]|4[13578]|6[1246]|7[1356]|9[1346])|5(?:0[14]|2[1-3589]|3[1357]|4[1246]|6[1-4]|7[1346]|8[13568]|9[1246])|6(?:0[356]|2[1-489]|3[124-6]|4[1347]|6[13]|7[12579]|8[1-356]|9[135])|7(?:2[1-7]|3[1357]|4[145]|6[1-5]|7[1-4])|8(?:21|3[1468]|4[1347]|6[0135-9]|7[1467]|8[136])|9(?:0[12479]|2[1358]|3[1357]|4[134679]|6[1-9]|7[136]|8[147]|9[1468]))"]
+,[,"(\\d{4})(\\d{2,11})","$1 $2",["[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:[3569][02-46-9]|4[2-4679]|7[2-467]|8[2-46-8])","[24-6]|[7-9](?:\\d[1-9]|[1-9]\\d)|3(?:3(?:0[1-467]|2[127-9]|3[124578]|[46][1246]|7[1257-9]|8[1256]|9[145])|4(?:2[135]|3[1357]|4[13578]|6[1246]|7[1356]|9[1346])|5(?:0[14]|2[1-3589]|3[1357]|4[1246]|6[1-4]|7[1346]|8[13568]|9[1246])|6(?:0[356]|2[1-489]|3[124-6]|4[1347]|6[13]|7[12579]|8[1-356]|9[135])|7(?:2[1-7]|3[1357]|4[145]|6[1-5]|7[1-4])|8(?:21|3[1468]|4[1347]|6[0135-9]|7[1467]|8[136])|9(?:0[12479]|2[1358]|3[1357]|4[134679]|6[1-9]|7[136]|8[147]|9[1468]))"]
 ,"0$1","",0]
-,[,"(\\d{5})(\\d{1,10})","$1/$2",["3"]
+,[,"(\\d{5})(\\d{1,10})","$1 $2",["3"]
 ,"0$1","",0]
 ,[,"(1\\d{2})(\\d{7,8})","$1 $2",["1[5-7]"]
 ,"0$1","",0]
@@ -1945,7 +1931,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"NA","NA"]
 ]
 ,"GR":[,[,,"[26-9]\\d{9}","\\d{10}"]
-,[,,"2(?:1\\d{2}|2(?:3[1-8]|4[1-7]|5[1-4]|6[1-8]|7[1-5]|[289][1-9])|3(?:1\\d|2[1-5]|3[1-4]|[45][1-3]|7[1-7]|8[1-6]|9[1-79])|4(?:1\\d|2[1-8]|3[1-4]|4[13-5]|6[1-578]|9[1-5])|5(?:1\\d|2[1-3]|4[124]|5[1-6]|[39][1-4])|6(?:1\\d|3[124]|4[1-7]|5[13-9]|[269][1-6]|7[14]|8[1-5])|7(?:1\\d|2[1-5]|3[1-6]|4[1-7]|5[1-57]|6[134]|9[15-7])|8(?:1\\d|2[1-5]|[34][1-4]|9[1-7]))\\d{6}","\\d{10}"]
+,[,,"2(?:1\\d{2}|2(?:3[1-8]|4[1-7]|5[1-4]|6[1-8]|7[1-5]|[289][1-9])|3(?:1\\d|2[1-57]|3[1-4]|[45][1-3]|7[1-7]|8[1-6]|9[1-79])|4(?:1\\d|2[1-8]|3[1-4]|4[13-5]|6[1-578]|9[1-5])|5(?:1\\d|2[1-3]|4[124]|5[1-6]|[39][1-4])|6(?:1\\d|3[124]|4[1-7]|5[13-9]|[269][1-6]|7[14]|8[1-5])|7(?:1\\d|2[1-5]|3[1-6]|4[1-7]|5[1-57]|6[134]|9[15-7])|8(?:1\\d|2[1-5]|[34][1-4]|9[1-7]))\\d{6}","\\d{10}"]
 ,[,,"69\\d{8}","\\d{10}"]
 ,[,,"800\\d{7}","\\d{10}"]
 ,[,,"90[19]\\d{7}","\\d{10}"]
@@ -2070,16 +2056,18 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"NA","NA"]
 ]
 ,"HR":[,[,,"[1-7]\\d{5,8}|[89]\\d{6,11}","\\d{6,12}"]
-,[,,"(?:1|6[029])\\d{7}|(?:2[0-3]|3[1-5]|4[02-47-9]|5[1-3])\\d{6}","\\d{6,9}"]
+,[,,"1\\d{7}|(?:2[0-3]|3[1-5]|4[02-47-9]|5[1-3])\\d{6}","\\d{6,8}"]
 ,[,,"9[1257-9]\\d{6,10}","\\d{8,12}"]
 ,[,,"80[01]\\d{4,7}","\\d{7,10}"]
-,[,,"6[145]\\d{4,7}","\\d{6,9}"]
+,[,,"6(?:[09]\\d{7}|[145]\\d{4,7})","\\d{6,9}"]
 ,[,,"NA","NA"]
 ,[,,"7[45]\\d{4,7}","\\d{6,9}"]
 ,[,,"NA","NA"]
 ,"HR",385,"00","0",,,"0",,,,[[,"(1)(\\d{4})(\\d{3})","$1 $2 $3",["1"]
 ,"0$1","",0]
-,[,"(6[029])(\\d{4})(\\d{3})","$1 $2 $3",["6[029]"]
+,[,"(6[09])(\\d{4})(\\d{3})","$1 $2 $3",["6[09]"]
+,"0$1","",0]
+,[,"(62)(\\d{3})(\\d{3,4})","$1 $2 $3",["62"]
 ,"0$1","",0]
 ,[,"([2-5]\\d)(\\d{3})(\\d{3})","$1 $2 $3",["[2-5]"]
 ,"0$1","",0]
@@ -2100,7 +2088,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ]
 ,,[,,"NA","NA"]
 ,,,[,,"NA","NA"]
-,[,,"NA","NA"]
+,[,,"62\\d{6,7}","\\d{8,9}"]
 ,,[,,"1(?:12|92)|9[34]","\\d{2,3}"]
 ,[,,"NA","NA"]
 ]
@@ -3613,9 +3601,9 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,,[,,"111","\\d{3}"]
 ,[,,"NA","NA"]
 ]
-,"OM":[,[,,"(?:2[3-6]|5|9[2-9])\\d{6}|800\\d{5,6}","\\d{7,9}"]
-,[,,"2[3-6]\\d{6}","\\d{8}"]
-,[,,"9[2-9]\\d{6}","\\d{8}"]
+,"OM":[,[,,"(?:2[2-6]|5|9[1-9])\\d{6}|800\\d{5,6}","\\d{7,9}"]
+,[,,"2[2-6]\\d{6}","\\d{8}"]
+,[,,"9[1-9]\\d{6}","\\d{8}"]
 ,[,,"8007\\d{4,5}|500\\d{4}","\\d{7,9}"]
 ,[,,"NA","NA"]
 ,[,,"NA","NA"]
@@ -4061,15 +4049,15 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,,[,,"99[7-9]","\\d{3}"]
 ,[,,"NA","NA"]
 ]
-,"SB":[,[,,"[1-8]\\d{4,6}","\\d{5,7}"]
+,"SB":[,[,,"[1-9]\\d{4,6}","\\d{5,7}"]
 ,[,,"(?:1[4-79]|[23]\\d|4[01]|5[03]|6[0-37])\\d{3}","\\d{5}"]
-,[,,"48\\d{3}|7(?:4\\d|5[025-8]|6[0-6])\\d{4}|8[4-8]\\d{5}","\\d{5,7}"]
+,[,,"48\\d{3}|7(?:[46-8]\\d|5[025-9]|90)\\d{4}|8[4-8]\\d{5}|9(?:[46]\\d|5[0-46-9]|7[0-689]|8[0-79]|9[0-8])\\d{4}","\\d{5,7}"]
 ,[,,"1[38]\\d{3}","\\d{5}"]
 ,[,,"NA","NA"]
 ,[,,"NA","NA"]
 ,[,,"NA","NA"]
 ,[,,"5[12]\\d{3}","\\d{5}"]
-,"SB",677,"0[01]",,,,,,,,[[,"(\\d{3})(\\d{4})","$1 $2",["[78]"]
+,"SB",677,"0[01]",,,,,,,,[[,"(\\d{3})(\\d{4})","$1 $2",["[7-9]"]
 ,"","",0]
 ]
 ,,[,,"NA","NA"]
@@ -5027,7 +5015,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ,[,,"(?:1[0-8]|2[1-478]|3[1-69]|4\\d|5[1346-8])\\d{7}","\\d{8,9}"]
 ,[,,"(?:7[1-4689]|8[1-5789])\\d{3,7}","\\d{5,9}"]
 ,[,,"80\\d{7}","\\d{9}"]
-,[,,"86[1-9]\\d{6}","\\d{9}"]
+,[,,"86[2-9]\\d{6}","\\d{9}"]
 ,[,,"860\\d{6}","\\d{9}"]
 ,[,,"NA","NA"]
 ,[,,"87\\d{7}","\\d{9}"]
@@ -5042,7 +5030,7 @@ i18n.phonenumbers.metadata.countryToMetadata = {
 ]
 ,,[,,"NA","NA"]
 ,,,[,,"NA","NA"]
-,[,,"NA","NA"]
+,[,,"861\\d{6}","\\d{9}"]
 ,,[,,"1(?:01(?:11|77)|12)","\\d{3,5}"]
 ,[,,"NA","NA"]
 ]
index 0d238b4..a73e3c1 100644 (file)
@@ -265,7 +265,7 @@ i18n.phonenumbers.PhoneNumberUtil.DIGIT_MAPPINGS = {
 /**
  * A map that contains characters that are essential when dialling. That means
  * any of the characters in this map must not be removed from a number when
- * dialing, otherwise the call will not reach the intended destination.
+ * dialling, otherwise the call will not reach the intended destination.
  *
  * @const
  * @type {!Object.<string, string>}
@@ -1126,30 +1126,19 @@ i18n.phonenumbers.PhoneNumberUtil.convertAlphaCharactersInNumber =
  */
 i18n.phonenumbers.PhoneNumberUtil.prototype.getLengthOfGeographicalAreaCode =
     function(number) {
-
-  if (number == null) {
-    return 0;
-  }
-  /** @type {?string} */
-  var regionCode = this.getRegionCodeForNumber(number);
-  if (!this.isValidRegionCode_(regionCode)) {
+  /** @type {i18n.phonenumbers.PhoneMetadata} */
+  var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
+  if (metadata == null) {
     return 0;
   }
-  /** @type {i18n.phonenumbers.PhoneMetadata} */
-  var metadata = this.getMetadataForRegion(regionCode);
-  // If a country doesn't use a national prefix, and this number doesn't have an
-  // Italian leading zero, we assume it is a closed dialling plan with no area
-  // codes.
+  // If a country doesn't use a national prefix, and this number doesn't have
+  // an Italian leading zero, we assume it is a closed dialling plan with no
+  // area codes.
   if (!metadata.hasNationalPrefix() && !number.hasItalianLeadingZero()) {
     return 0;
   }
 
-  /** @type {i18n.phonenumbers.PhoneNumberType} */
-  var type = this.getNumberTypeHelper_(
-      this.getNationalSignificantNumber(number), metadata);
-  // Most numbers other than the two types below have to be dialled in full.
-  if (type != i18n.phonenumbers.PhoneNumberType.FIXED_LINE &&
-      type != i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE) {
+  if (!this.isNumberGeographical_(number)) {
     return 0;
   }
 
@@ -1301,6 +1290,26 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formattingRuleHasFirstGroupOnly =
 
 
 /**
+ * Tests whether a phone number has a geographical association. It checks if
+ * the number is associated to a certain region in the country where it belongs
+ * to. Note that this doesn't verify if the number is actually in use.
+ *
+ * @param {i18n.phonenumbers.PhoneNumber} phoneNumber The phone number to test.
+ * @return {boolean} true if the phone number has a geographical association.
+ * @private
+ */
+i18n.phonenumbers.PhoneNumberUtil.prototype.isNumberGeographical_ =
+    function(phoneNumber) {
+  /** @type {i18n.phonenumbers.PhoneNumberType} */
+  var numberType = this.getNumberType(phoneNumber);
+  // TODO: Include mobile phone numbers from countries like Indonesia, which
+  // has some mobile numbers that are geographical.
+  return numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE ||
+      numberType == i18n.phonenumbers.PhoneNumberType.FIXED_LINE_OR_MOBILE;
+};
+
+
+/**
  * Helper function to check region code is not unknown or null.
  *
  * @param {?string} regionCode the ISO 3166-1 two-letter region code.
@@ -1360,6 +1369,11 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.format =
     function(number, numberFormat) {
 
   if (number.getNationalNumber() == 0 && number.hasRawInput()) {
+    // Unparseable numbers that kept their raw input just use that.
+    // This is the only case where a number can be formatted as E164 without a
+    // leading '+' symbol (but the original number wasn't parseable anyway).
+    // TODO: Consider removing the 'if' above so that unparseable strings
+    // without raw input format to the empty string instead of "+00"
     /** @type {string} */
     var rawInput = number.getRawInputOrDefault();
     if (rawInput.length > 0) {
@@ -1371,22 +1385,26 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.format =
   /** @type {string} */
   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
   if (numberFormat == i18n.phonenumbers.PhoneNumberFormat.E164) {
-    // Early exit for E164 case since no formatting of the national number needs
-    // to be applied. Extensions are not formatted.
+    // Early exit for E164 case (even if the country calling code is invalid)
+    // since no formatting of the national number needs to be applied.
+    // Extensions are not formatted.
     return this.prefixNumberWithCountryCallingCode_(
         countryCallingCode, i18n.phonenumbers.PhoneNumberFormat.E164,
         nationalSignificantNumber, '');
   }
+  if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
+    return nationalSignificantNumber;
+  }
   // Note getRegionCodeForCountryCode() is used because formatting information
   // for regions which share a country calling code is contained by only one
   // region for performance reasons. For example, for NANPA regions it will be
   // contained in the metadata for US.
   /** @type {string} */
   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
-  if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
-    return nationalSignificantNumber;
-  }
 
+  // Metadata cannot be null because the country calling code is valid (which
+  // means that the region code cannot be ZZ and must be one of our supported
+  // region codes).
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadata =
       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
@@ -1426,15 +1444,16 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatByPattern =
   var countryCallingCode = number.getCountryCodeOrDefault();
   /** @type {string} */
   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
+  if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
+    return nationalSignificantNumber;
+  }
   // Note getRegionCodeForCountryCode() is used because formatting information
   // for regions which share a country calling code is contained by only one
   // region for performance reasons. For example, for NANPA regions it will be
   // contained in the metadata for US.
   /** @type {string} */
   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
-  if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
-    return nationalSignificantNumber;
-  }
+  // Metadata cannot be null because the country calling code is valid
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadata =
       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
@@ -1508,16 +1527,17 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
   var countryCallingCode = number.getCountryCodeOrDefault();
   /** @type {string} */
   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
+  if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
+    return nationalSignificantNumber;
+  }
+
   // Note getRegionCodeForCountryCode() is used because formatting information
   // for regions which share a country calling code is contained by only one
   // region for performance reasons. For example, for NANPA regions it will be
   // contained in the metadata for US.
   /** @type {string} */
   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
-  if (!this.hasValidCountryCallingCode_(countryCallingCode)) {
-    return nationalSignificantNumber;
-  }
-
+  // Metadata cannot be null because the country calling code is valid.
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadata =
       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
@@ -1702,9 +1722,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
     }
   } else if (countryCallingCode ==
                  this.getCountryCodeForValidRegion_(regionCallingFrom)) {
-    // For regions that share a country calling code, the country calling code
-    // need not be dialled. This also applies when dialling within a region, so
-    // this if clause covers both these cases. Technically this is the case for
+    // If regions share a country calling code, the country calling code need
+    // not be dialled. This also applies when dialling within a region, so this
+    // if clause covers both these cases. Technically this is the case for
     // dialling from La Reunion to other overseas departments of France (French
     // Guiana, Martinique, Guadeloupe), but not vice versa - so we don't cover
     // this edge case for now and for those cases return the version including
@@ -1713,6 +1733,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
     return this.format(number,
                        i18n.phonenumbers.PhoneNumberFormat.NATIONAL);
   }
+  // Metadata cannot be null because we checked 'isValidRegionCode()' above.
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadataForRegionCallingFrom =
       this.getMetadataForRegion(regionCallingFrom);
@@ -1736,6 +1757,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatOutOfCountryCallingNumber =
 
   /** @type {string} */
   var regionCode = this.getRegionCodeForCountryCode(countryCallingCode);
+  // Metadata cannot be null because the country calling code is valid.
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadataForRegion =
       this.getMetadataForRegionOrCallingCode_(countryCallingCode, regionCode);
@@ -1831,6 +1853,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
         formattedNumber = nationalFormat;
         break;
       }
+      // Metadata cannot be null here because getNddPrefixForRegion() (above)
+      // returns null if there is no metadata for the region.
       /** @type {i18n.phonenumbers.PhoneMetadata} */
       var metadata = this.getMetadataForRegion(regionCode);
       /** @type {string} */
@@ -1838,6 +1862,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
       /** @type {i18n.phonenumbers.NumberFormat} */
       var formatRule = this.chooseFormattingPatternForNumber_(
           metadata.numberFormatArray(), nationalNumber);
+      // The format rule could still be null here if the national number was 0
+      // and there was no raw input (this should not be possible for numbers
+      // generated by the phonenumber library as they would also not have a
+      // country calling code and we would have exited earlier).
+      if (formatRule == null) {
+        formattedNumber = nationalFormat;
+        break;
+      }
       // When the format we apply to this number doesn't contain national
       // prefix, we can just return the national format.
       // TODO: Refactor the code below with the code in
@@ -1875,15 +1907,22 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.formatInOriginalFormat =
   // If no digit is inserted/removed/modified as a result of our formatting, we
   // return the formatted phone number; otherwise we return the raw input the
   // user entered.
-  return (formattedNumber != null &&
-          i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
-              i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
-              true /* remove non matches */) ==
-          i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(rawInput,
-              i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
-              true /* remove non matches */)) ?
-      formattedNumber :
-      rawInput;
+  if (formattedNumber != null && rawInput.length > 0) {
+    /** @type {string} */
+    var normalizedFormattedNumber =
+        i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(formattedNumber,
+            i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
+            true /* remove non matches */);
+    /** @type {string} */
+    var normalizedRawInput =
+        i18n.phonenumbers.PhoneNumberUtil.normalizeHelper_(rawInput,
+            i18n.phonenumbers.PhoneNumberUtil.DIALLABLE_CHAR_MAPPINGS_,
+            true /* remove non matches */);
+    if (normalizedFormattedNumber != normalizedRawInput) {
+      formattedNumber = rawInput;
+    }
+  }
+  return formattedNumber;
 };
 
 
@@ -2032,7 +2071,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
     if (this.isNANPACountry(regionCallingFrom)) {
       return countryCode + ' ' + rawInput;
     }
-  } else if (this.isValidRegionCode_(regionCallingFrom) &&
+  } else if (metadataForRegionCallingFrom != null &&
       countryCode == this.getCountryCodeForValidRegion_(regionCallingFrom)) {
     /** @type {i18n.phonenumbers.NumberFormat} */
     var formattingPattern = this.chooseFormattingPatternForNumber_(
@@ -2076,6 +2115,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
   }
   /** @type {string} */
   var regionCode = this.getRegionCodeForCountryCode(countryCode);
+  // Metadata cannot be null because the country calling code is valid.
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadataForRegion =
       this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
@@ -2230,7 +2270,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.chooseFormattingPatternForNumber_ =
 
 
 /**
- * Note that carrierCode is optional - if NULL or an empty string, no carrier
+ * Note that carrierCode is optional - if null or an empty string, no carrier
  * code replacement will take place.
  *
  * @param {string} nationalNumber a string of characters representing a phone
@@ -2466,16 +2506,14 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberType =
 
   /** @type {?string} */
   var regionCode = this.getRegionCodeForNumber(number);
-  if (!this.isValidRegionCode_(regionCode) &&
-      i18n.phonenumbers.PhoneNumberUtil.REGION_CODE_FOR_NON_GEO_ENTITY !=
-      regionCode) {
+  /** @type {i18n.phonenumbers.PhoneMetadata} */
+  var metadata = this.getMetadataForRegionOrCallingCode_(
+      number.getCountryCodeOrDefault(), regionCode);
+  if (metadata == null) {
     return i18n.phonenumbers.PhoneNumberType.UNKNOWN;
   }
   /** @type {string} */
   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
-  /** @type {i18n.phonenumbers.PhoneMetadata} */
-  var metadata = this.getMetadataForRegionOrCallingCode_(
-      number.getCountryCodeOrDefault(), regionCode);
   return this.getNumberTypeHelper_(nationalSignificantNumber, metadata);
 };
 
@@ -2545,6 +2583,9 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getNumberTypeHelper_ =
 
 
 /**
+ * Returns the metadata for the given region code or {@code null} if the region
+ * code is invalid or unknown.
+ *
  * @param {?string} regionCode
  * @return {i18n.phonenumbers.PhoneMetadata}
  */
@@ -2627,6 +2668,10 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isValidNumber = function(number) {
  * After this, the specific number pattern rules for the region are examined.
  * This is useful for determining for example whether a particular number is
  * valid for Canada, rather than just a valid NANPA number.
+ * Warning: In most cases, you want to use {@link #isValidNumber} instead. For
+ * example, this method will mark numbers from British Crown dependencies such
+ * as the Isle of Man as invalid for the region "GB" (United Kingdom), since it
+ * has its own region code, "IM", which may be undesirable.
  *
  * @param {i18n.phonenumbers.PhoneNumber} number the phone number that we want
  *     to validate.
@@ -2721,6 +2766,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.
   for (var i = 0; i < regionCodesLength; i++) {
     regionCode = regionCodes[i];
     // If leadingDigits is present, use this. Otherwise, do full validation.
+    // Metadata cannot be null because the region codes come from the country
+    // calling code map.
     /** @type {i18n.phonenumbers.PhoneMetadata} */
     var metadata = this.getMetadataForRegion(regionCode);
     if (metadata.hasLeadingDigits()) {
@@ -2757,6 +2804,25 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodeForCountryCode =
 
 
 /**
+ * Returns a list with the region codes that match the specific country calling
+ * code. For non-geographical country calling codes, the region code 001 is
+ * returned. Also, in the case of no region code being found, an empty list is
+ * returned.
+ *
+ * @param {number} countryCallingCode the country calling code.
+ * @return {Array.<string>}
+ */
+i18n.phonenumbers.PhoneNumberUtil.prototype.getRegionCodesForCountryCode =
+    function(countryCallingCode) {
+
+  /** @type {Array.<string>} */
+  var regionCodes =
+      i18n.phonenumbers.metadata.countryCodeToRegionCodeMap[countryCallingCode];
+  return regionCodes == null ? [] : regionCodes;
+};
+
+
+/**
  * Returns the country calling code for a specific region. For example, this
  * would be 1 for the United States, and 64 for New Zealand.
  *
@@ -2784,6 +2850,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForRegion =
  *     calling code for.
  * @return {number} the country calling code for the region denoted by
  *     regionCode.
+ * @throws {string} if the region is invalid
  * @private
  */
 i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForValidRegion_ =
@@ -2791,7 +2858,10 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForValidRegion_ =
 
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadata = this.getMetadataForRegion(regionCode);
-  return metadata.getCountryCodeOrDefault();
+  if (metadata == null) {
+    throw 'Invalid region code: ' + regionCode;
+  }
+  return metadata.getCountryCode();
 };
 
 
@@ -2816,11 +2886,11 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.getCountryCodeForValidRegion_ =
  */
 i18n.phonenumbers.PhoneNumberUtil.prototype.getNddPrefixForRegion = function(
     regionCode, stripNonDigits) {
-  if (!this.isValidRegionCode_(regionCode)) {
-    return null;
-  }
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadata = this.getMetadataForRegion(regionCode);
+  if (metadata == null) {
+    return null;
+  }
   /** @type {string} */
   var nationalPrefix = metadata.getNationalPrefixOrDefault();
   // If no national prefix was found, we return null.
@@ -2865,7 +2935,8 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNANPACountry =
 i18n.phonenumbers.PhoneNumberUtil.prototype.isLeadingZeroPossible =
     function(countryCallingCode) {
   /** @type {i18n.phonenumbers.PhoneMetadata} */
-  var mainMetadataForCallingCode = this.getMetadataForRegion(
+  var mainMetadataForCallingCode = this.getMetadataForRegionOrCallingCode_(
+      countryCallingCode,
       this.getRegionCodeForCountryCode(countryCallingCode));
   return mainMetadataForCallingCode != null &&
       mainMetadataForCallingCode.getLeadingZeroPossibleOrDefault();
@@ -2982,6 +3053,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isPossibleNumberWithReason =
   }
   /** @type {string} */
   var regionCode = this.getRegionCodeForCountryCode(countryCode);
+  // Metadata cannot be null because the country calling code is valid.
   /** @type {i18n.phonenumbers.PhoneMetadata} */
   var metadata =
       this.getMetadataForRegionOrCallingCode_(countryCode, regionCode);
@@ -3621,6 +3693,7 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.parseHelper_ =
     /** @type {string} */
     var phoneNumberRegion = this.getRegionCodeForCountryCode(countryCode);
     if (phoneNumberRegion != defaultRegion) {
+      // Metadata cannot be null because the country calling code is valid.
       regionMetadata = this.getMetadataForRegionOrCallingCode_(
           countryCode, phoneNumberRegion);
     }
@@ -3930,15 +4003,13 @@ i18n.phonenumbers.PhoneNumberUtil.prototype.isNationalNumberSuffixOfTheOther_ =
  */
 i18n.phonenumbers.PhoneNumberUtil.prototype.canBeInternationallyDialled =
     function(number) {
-  /** @type {?string} */
-  var regionCode = this.getRegionCodeForNumber(number);
-  if (!this.isValidRegionCode_(regionCode)) {
+  /** @type {i18n.phonenumbers.PhoneMetadata} */
+  var metadata = this.getMetadataForRegion(this.getRegionCodeForNumber(number));
+  if (metadata == null) {
     // Note numbers belonging to non-geographical entities (e.g. +800 numbers)
     // are always internationally diallable, and will be caught here.
     return true;
   }
-  /** @type {i18n.phonenumbers.PhoneMetadata} */
-  var metadata = this.getMetadataForRegion(regionCode);
   /** @type {string} */
   var nationalSignificantNumber = this.getNationalSignificantNumber(number);
   return !this.isNumberMatchingDesc_(nationalSignificantNumber,
index a813025..62359e4 100644 (file)
@@ -25,6 +25,7 @@
  * @author Nikolaos Trogkanis
  */
 
+goog.require('goog.array');
 goog.require('goog.testing.jsunit');
 goog.require('i18n.phonenumbers.PhoneNumberUtil');
 goog.require('i18n.phonenumbers.RegionCode');
@@ -35,6 +36,9 @@ var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance();
 
 
 // Set up some test numbers to re-use.
+// TODO: Rewrite this as static functions that return new numbers each time to
+// avoid any risk of accidental changes to mutable static state affecting many
+// tests.
 /** @type {i18n.phonenumbers.PhoneNumber} */
 var ALPHA_NUMERIC_NUMBER = new i18n.phonenumbers.PhoneNumber();
 ALPHA_NUMERIC_NUMBER.setCountryCode(1);
@@ -223,6 +227,12 @@ var UNIVERSAL_PREMIUM_RATE = new i18n.phonenumbers.PhoneNumber();
 UNIVERSAL_PREMIUM_RATE.setCountryCode(979);
 UNIVERSAL_PREMIUM_RATE.setNationalNumber(123456789);
 
+
+/** @type {i18n.phonenumbers.PhoneNumber} */
+var UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT = new i18n.phonenumbers.PhoneNumber();
+UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT.setCountryCode(2);
+UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT.setNationalNumber(12345);
+
 var RegionCode = i18n.phonenumbers.RegionCode;
 
 function testGetInstanceLoadUSMetadata() {
@@ -300,13 +310,24 @@ function testGetInstanceLoadInternationalTollFreeMetadata() {
   assertEquals('12345678', metadata.getTollFree().getExampleNumber());
 }
 
+function testIsNumberGeographical() {
+  // Bahamas, mobile phone number.
+  assertFalse(phoneUtil.isNumberGeographical_(BS_MOBILE));
+  // Australian fixed line number.
+  assertTrue(phoneUtil.isNumberGeographical_(AU_NUMBER));
+  // International toll free number.
+  assertFalse(phoneUtil.isNumberGeographical_(INTERNATIONAL_TOLL_FREE));
+}
+
 function testIsLeadingZeroPossible() {
   // Italy
   assertTrue(phoneUtil.isLeadingZeroPossible(39));
   // USA
   assertFalse(phoneUtil.isLeadingZeroPossible(1));
-  // International toll free numbers
-  assertFalse(phoneUtil.isLeadingZeroPossible(800));
+  // International toll free
+  assertTrue(phoneUtil.isLeadingZeroPossible(800));
+  // International premium-rate
+  assertFalse(phoneUtil.isLeadingZeroPossible(979));
   // Not in metadata file, just default to false.
   assertFalse(phoneUtil.isLeadingZeroPossible(888));
 }
@@ -880,6 +901,9 @@ function testFormatWithCarrierCode() {
   // We don't support this for the US so there should be no change.
   assertEquals('650 253 0000',
                phoneUtil.formatNationalNumberWithCarrierCode(US_NUMBER, '15'));
+  // Invalid country code should just get the NSN.
+  assertEquals('12345', phoneUtil.formatNationalNumberWithCarrierCode(
+                   UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT, '89'));
 }
 
 function testFormatWithPreferredCarrierCode() {
@@ -1237,6 +1261,11 @@ function testFormatInOriginalFormat() {
   var numberWithoutStar = phoneUtil.parseAndKeepRawInput('1234', RegionCode.JP);
   assertEquals('1234', phoneUtil.formatInOriginalFormat(numberWithoutStar,
                                                         RegionCode.JP));
+
+  // Test an invalid national number without raw input is just formatted as the
+  // national number.
+  assertEquals('650253000',
+      phoneUtil.formatInOriginalFormat(US_SHORT_BY_ONE_NUMBER, RegionCode.US));
 }
 
 function testIsPremiumRate() {
@@ -1488,6 +1517,21 @@ function testGetRegionCodeForNumber() {
       phoneUtil.getRegionCodeForNumber(UNIVERSAL_PREMIUM_RATE));
 }
 
+function testGetRegionCodesForCountryCode() {
+  /** @type {Array.<string>} */
+  var regionCodesForNANPA = phoneUtil.getRegionCodesForCountryCode(1);
+  assertTrue(goog.array.contains(regionCodesForNANPA, RegionCode.US));
+  assertTrue(goog.array.contains(regionCodesForNANPA, RegionCode.BS));
+  assertTrue(goog.array.contains(
+      phoneUtil.getRegionCodesForCountryCode(44), RegionCode.GB));
+  assertTrue(goog.array.contains(
+      phoneUtil.getRegionCodesForCountryCode(49), RegionCode.DE));
+  assertTrue(goog.array.contains(
+      phoneUtil.getRegionCodesForCountryCode(800), RegionCode.UN001));
+  // Test with invalid country calling code.
+  assertTrue(goog.array.isEmpty(phoneUtil.getRegionCodesForCountryCode(-1)));
+}
+
 function testGetCountryCodeForRegion() {
   assertEquals(1, phoneUtil.getCountryCodeForRegion(RegionCode.US));
   assertEquals(64, phoneUtil.getCountryCodeForRegion(RegionCode.NZ));
@@ -2838,12 +2882,14 @@ function testCountryWithNoNumberDesc() {
                                                          RegionCode.AD));
 }
 
-function testUnknownCountryCallingCodeForValidation() {
-  /** @type {i18n.phonenumbers.PhoneNumber} */
-  var invalidNumber = new i18n.phonenumbers.PhoneNumber();
-  invalidNumber.setCountryCode(0);
-  invalidNumber.setNationalNumber(1234);
-  assertFalse(phoneUtil.isValidNumber(invalidNumber));
+function testUnknownCountryCallingCode() {
+  var PNF = i18n.phonenumbers.PhoneNumberFormat;
+  assertFalse(phoneUtil.isValidNumber(UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT));
+  // It's not very well defined as to what the E164 representation for a number
+  // with an invalid country calling code is, but just prefixing the country
+  // code and national number is about the best we can do.
+  assertEquals('+212345',
+               phoneUtil.format(UNKNOWN_COUNTRY_CODE_NO_RAW_INPUT, PNF.E164));
 }
 
 function testIsNumberMatchMatches() {