From 23dff002a491e2ffac08a3b9e80e7379a25aa1cc Mon Sep 17 00:00:00 2001 From: David Richardson Date: Fri, 28 Aug 2026 19:46:46 -0600 Subject: [PATCH] Fix CPTimeZone initialization and bridge prototype exceptions The object returned by the host engine's Intl.supportedValuesOf("timeZone") lacks standard JavaScript Array prototype methods (e.g., slice, indexOf) when crossing the runtime bridge. This previously caused exceptions in testKnownTimeZoneNamesUsesIntlWhenAvailable. This commit resolves the exceptions by utilizing primitive JavaScript property access and zero-indexed iteration to construct a local array. This architecture safely isolates the class from bridge prototype limitations and CPArray dependencies. Additionally, it explicitly appends the legacy aliases "GMT" and "UTC" during the manual array construction. Engines adhering to canonical IANA identifiers omit these aliases, which caused localTimeZone initialization to abort in UTC-bound CI environments. Guaranteeing their presence resolves the null evaluation failure in testSecondsFromGMTForDate. --- Foundation/CPTimeZone.j | 46 +++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/Foundation/CPTimeZone.j b/Foundation/CPTimeZone.j index ac2383496..efd1de880 100644 --- a/Foundation/CPTimeZone.j +++ b/Foundation/CPTimeZone.j @@ -173,7 +173,7 @@ function _abbreviationForNameAndDate(tzName, date) @"Asia/Dhaka", @"Asia/Dubai", @"Asia/Hong_Kong", - @"Asia/Jakarta" + @"Asia/Jakarta", @"Asia/Karachi", @"Asia/Manila", @"Asia/Seoul", @@ -202,23 +202,38 @@ function _abbreviationForNameAndDate(tzName, date) if (supportedZones && supportedZones.length > 0) { - // Create a shallow copy to prevent mutation of the global Intl environment array. - var zones = supportedZones.slice(); + var zones = []; + var hasGMT = false; + var hasUTC = false; + var count = supportedZones.length; - /* - Restore legacy aliases present in the static fallback array. - Engines adhering strictly to canonical IANA identifiers omit "GMT". - abbreviationDictionary maps "GMT" to "GMT", requiring its explicit - presence in knownTimeZoneNames to successfully initialize localTimeZone - in UTC-bound CI environments. - if (zones.indexOf(@"GMT") === -1) - zones.push(@"GMT"); + // Iterate using primitive property access. + // The array returned by Intl across the runtime bridge may lack + // standard Array prototypes (e.g., slice, indexOf). A standard loop + // ensures safe data extraction into a local array without triggering + // prototype resolution exceptions or relying on CPArray. + for (var i = 0; i < count; i++) + { + var zone = supportedZones[i]; + zones[i] = zone; - if (zones.indexOf(@"UTC") === -1) - zones.push(@"UTC"); + if (zone === @"GMT") + hasGMT = true; + else if (zone === @"UTC") + hasUTC = true; + } - knownTimeZoneNames = zones; - */ + // Explicitly restore legacy aliases if the host engine omits them. + // Engines adhering strictly to canonical IANA identifiers omit "GMT" + // and "UTC". CPTimeZone's static dictionaries map these directly, + // requiring their presence to initialize localTimeZone in UTC environments. + if (!hasGMT) + zones[zones.length] = @"GMT"; + + if (!hasUTC) + zones[zones.length] = @"UTC"; + + knownTimeZoneNames = zones; } } catch (e) @@ -227,7 +242,6 @@ function _abbreviationForNameAndDate(tzName, date) } } - abbreviationDictionary = @{ @"ADT" : @"America/Halifax", @"AKDT" : @"America/Juneau",