From 9148fc8face8e6d396e96bc9d078be6e141f67b3 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Sat, 25 Jul 2026 02:23:33 +0200 Subject: [PATCH] fix: use libphonenumber getRegionCodeForNumber for country code resolution parsePhone() derived countryISOCode from a hand-rolled, incomplete prefixes table via findCountryISO2, ignoring the bundled libphonenumber's getRegionCodeForNumber(). NANP area codes missing from the table (787, 809, 829, 268, 284, 340, 649, 784, 868, 869, ...) returned countryISOCode "nothing" even though the same result object carried the correct areaCode parsed by libphonenumber. This produced a self-contradictory result, e.g. parsePhone("17871234567") returned { areaCode: "787", countryISOCode: "nothing" } -- the library contradicted its own bundled libphonenumber, which resolves 787 to PR. Overlay 939 resolved to "PR" while the primary 787 resolved to "nothing". Fix: after parsing the number with the existing default region, prefer the authoritative region returned by PhoneNumberUtil.getRegionCodeForNumber() for countryISOCode, falling back to the prefixes table only when libphonenumber cannot determine a region (e.g. invalid numbers). This keeps countryISOCode consistent with the areaCode libphonenumber already parses. Resolves all missing NANP area codes (787->PR, 809/829->DO, 268->AG, 284->VG, 340->VI, 649->TC, 784->VC, 868->TT, 869->KN) and preserves existing behavior (939->PR, 849->DO, 1202->US, and non-NANP such as +268 Eswatini). Added test.js (node assert) covering the RED cases, controls, and the internal-consistency check (areaCode vs countryISOCode). --- index.js | 2 ++ test.js | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 test.js diff --git a/index.js b/index.js index 7a70a36..d5fe3f0 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,8 @@ function parsePhone(e) { , d = o = null , i = t.getNationalSignificantNumber(r) , N = t.getLengthOfNationalDestinationCode(r); + var regionForNumber = t.getRegionCodeForNumber(r); + null != regionForNumber && (n = regionForNumber); N > 0 && (o = i.substring(0, N)); var d = e.substr(0, e.indexOf(i)) , a = i.substr((o || "").length) diff --git a/test.js b/test.js new file mode 100644 index 0000000..2d369f1 --- /dev/null +++ b/test.js @@ -0,0 +1,52 @@ +var assert = require("assert"); +var parsePhone = require("./index.js"); + +// Regression tests for NANP area codes that were missing from the hand-rolled +// prefixes table. The bundled libphonenumber's getRegionCodeForNumber() is now +// used to derive countryISOCode, so these resolve correctly instead of "nothing". + +// RED cases: previously returned countryISOCode "nothing". +assert.strictEqual(parsePhone("17871234567").countryISOCode, "PR", + '1787 (Puerto Rico primary area 787) must be "PR"'); +assert.strictEqual(parsePhone("18091234567").countryISOCode, "DO", + '1809 (Dominican Republic primary 809) must be "DO"'); +assert.strictEqual(parsePhone("18291234567").countryISOCode, "DO", + '1829 (Dominican Republic overlay 829) must be "DO"'); +assert.strictEqual(parsePhone("12681234567").countryISOCode, "AG", + '1268 (Antigua & Barbuda 268) must be "AG"'); + +// Additional NANP area codes that were also missing. +assert.strictEqual(parsePhone("12841234567").countryISOCode, "VG", + '1284 (British Virgin Islands 284) must be "VG"'); +assert.strictEqual(parsePhone("13401234567").countryISOCode, "VI", + '1340 (US Virgin Islands 340) must be "VI"'); +assert.strictEqual(parsePhone("16491234567").countryISOCode, "TC", + '1649 (Turks & Caicos 649) must be "TC"'); +assert.strictEqual(parsePhone("17841234567").countryISOCode, "VC", + '1784 (St Vincent 784) must be "VC"'); +assert.strictEqual(parsePhone("18681234567").countryISOCode, "TT", + '1868 (Trinidad & Tobago 868) must be "TT"'); +assert.strictEqual(parsePhone("18691234567").countryISOCode, "KN", + '1869 (St Kitts & Nevis 869) must be "KN"'); + +// Controls: behavior that already worked must be preserved. +assert.strictEqual(parsePhone("19391234567").countryISOCode, "PR", + '1939 (Puerto Rico overlay 939) must remain "PR"'); +assert.strictEqual(parsePhone("18491234567").countryISOCode, "DO", + '1849 (Dominican Republic overlay 849) must remain "DO"'); +assert.strictEqual(parsePhone("12025550104").countryISOCode, "US", + '1202 (US Washington DC) must remain "US"'); + +// The result object must be internally consistent: the areaCode that +// libphonenumber parsed and the countryISOCode must agree (the original +// self-contradiction had areaCode "787" but countryISOCode "nothing"). +var r787 = parsePhone("17871234567"); +assert.strictEqual(r787.areaCode, "787"); +assert.strictEqual(r787.countryISOCode, "PR"); + +// Non-NANP number must still resolve (Eswatini country calling code 268). +var sz = parsePhone("26822171234"); +assert.strictEqual(sz.countryISOCode, "SZ", + '+268 (Eswatini) must remain "SZ"'); + +console.log("All tests passed.");