From 4cb743dad2ba105c6fa3e92b4bac661ea69fdf95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Thu, 13 Jul 2017 16:02:37 +0200 Subject: [PATCH 1/6] build: run test-hash-seed at the end of test-v8 The v8 and test-hash-seed targets cannot be run in parallel because they need different copies of the deps/v8 directory. Ref: https://github.com/nodejs/node/pull/14004#issuecomment-314774773 PR-URL: https://github.com/nodejs/node/pull/14219 Reviewed-By: Michael Dawson Reviewed-By: Refael Ackermann Reviewed-By: Anna Henningsen --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cd78155b9a62df..5b67f92076bb09 100644 --- a/Makefile +++ b/Makefile @@ -259,13 +259,15 @@ test-timers: test-timers-clean: $(MAKE) --directory=tools clean -test-v8: v8 test-hash-seed +test-v8: v8 # note: performs full test unless QUICKCHECK is specified deps/v8/tools/run-tests.py --arch=$(V8_ARCH) \ --mode=$(BUILDTYPE_LOWER) $(V8_TEST_NO_I18N) $(QUICKCHECK_ARG) \ --no-presubmit \ --shell-dir=$(PWD)/deps/v8/out/$(V8_ARCH).$(BUILDTYPE_LOWER) \ $(TAP_V8) + @echo Testing hash seed + $(MAKE) test-hash-seed test-v8-intl: v8 # note: performs full test unless QUICKCHECK is specified From 3d357ebe782ffc97e9d6e8628c0cf99625606f07 Mon Sep 17 00:00:00 2001 From: karl Date: Mon, 5 Oct 2015 04:07:22 -0700 Subject: [PATCH 2/6] deps: backport e28183b5 from upstream V8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: Fix compilation with GCC 5.2 Fixes: ../../test/cctest/compiler/test-js-typed-lowering.cc:224:14: error: ‘kJSTypes’ defined but not used [-Werror=unused-variable] static Type* kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(), ../../src/bignum.cc: In member function ‘void v8::internal::Bignum::AssignDecimalString(Vector)’: ../../src/bignum.cc:80:6: error: assuming signed overflow does not occur when assuming that (X + c) < X is always false [-Werror=strict-overflow] ../../src/compiler/ia32/code-generator-ia32.cc:1366:3: required from here ../../src/base/logging.h:123:26: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] DEFINE_CHECK_OP_IMPL(EQ, ==) BUG= Review URL: https://codereview.chromium.org/1371823002 Cr-Commit-Position: refs/heads/master@{#31095} --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/bignum.cc | 4 +++- deps/v8/test/cctest/compiler/test-js-typed-lowering.cc | 4 ---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 9042d9bc826b57..b0b42462edb7ea 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 4 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 103 -#define V8_PATCH_LEVEL 49 +#define V8_PATCH_LEVEL 50 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/bignum.cc b/deps/v8/src/bignum.cc index e70987a82dc674..19077c4a1522b7 100644 --- a/deps/v8/src/bignum.cc +++ b/deps/v8/src/bignum.cc @@ -70,7 +70,9 @@ static uint64_t ReadUInt64(Vector buffer, int from, int digits_to_read) { uint64_t result = 0; - for (int i = from; i < from + digits_to_read; ++i) { + int to = from + digits_to_read; + + for (int i = from; i < to; ++i) { int digit = buffer[i] - '0'; DCHECK(0 <= digit && digit <= 9); result = result * 10 + digit; diff --git a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc index e512de89b2b9f2..41fee4e362d3fb 100644 --- a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc @@ -217,10 +217,6 @@ static Type* kNumberTypes[] = { Type::OrderedNumber(), Type::PlainNumber(), Type::Number()}; -static Type* kJSTypes[] = {Type::Undefined(), Type::Null(), Type::Boolean(), - Type::Number(), Type::String(), Type::Object()}; - - static Type* I32Type(bool is_signed) { return is_signed ? Type::Signed32() : Type::Unsigned32(); } From 2ac61928e852087e709e83b8af62a91ea7c2b7fe Mon Sep 17 00:00:00 2001 From: "akos.palfi" Date: Tue, 29 Sep 2015 15:10:13 -0700 Subject: [PATCH 3/6] deps: cherry pick d7f813b4 from V8 upstream Original commit message: GYP: Don't pass -Wno-format-pedantic to GCC. This flag is not understood correctly by GCC and breaks the GCC ARM and MIPS optdebug builds. Patch from Brendan Kirby BUG= Review URL: https://codereview.chromium.org/1369273003 Cr-Commit-Position: refs/heads/master@{#31013} --- deps/v8/build/standalone.gypi | 21 +++++++++++++++++++-- deps/v8/include/v8-version.h | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/deps/v8/build/standalone.gypi b/deps/v8/build/standalone.gypi index 2cd0b51d43601f..48f2194aaaa082 100644 --- a/deps/v8/build/standalone.gypi +++ b/deps/v8/build/standalone.gypi @@ -367,8 +367,25 @@ # things when their commandline changes). Nothing should ever read this # define. 'defines': ['CR_CLANG_REVISION= Date: Mon, 2 Oct 2017 13:23:47 -0700 Subject: [PATCH 4/6] build: fix make test-v8 --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 5b67f92076bb09..4cbc8b1dc55cf7 100644 --- a/Makefile +++ b/Makefile @@ -110,6 +110,7 @@ check: test cctest: all @out/$(BUILDTYPE)/$@ +v8: export GYPFLAGS += -Dclang=0 v8: tools/make-v8.sh $(MAKE) -C deps/v8 $(V8_ARCH).$(BUILDTYPE_LOWER) $(V8_BUILD_OPTIONS) From 82b243600c3f11e281e9e66584e719c9276208dc Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Fri, 22 Sep 2017 14:32:21 -0400 Subject: [PATCH 5/6] deps: backport bff3074 from V8 upstream Original commit message: Allow ICU to normalize time zones There's at least one case of a time zone alias: Asia/Kathmandu aliases Asia/Katmandu. ICU seems to normalize to the (deprecated) latter choice. V8 internationalization choked on this change; this patch interprets ICU's output more precisely and allows it. BUG=chromium:487322 R=jungshik,adamk LOG=Y Review URL: https://codereview.chromium.org/1509273007 Cr-Commit-Position: refs/heads/master@{#32769} PR-URL: https://github.com/nodejs/node/pull/15562 --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/i18n.js | 2 +- deps/v8/test/mjsunit/regress/regress-487322.js | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 deps/v8/test/mjsunit/regress/regress-487322.js diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 20282039beb27b..88682a0fa57b07 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 4 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 103 -#define V8_PATCH_LEVEL 51 +#define V8_PATCH_LEVEL 52 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/i18n.js b/deps/v8/src/i18n.js index 79e988062e9425..c6675679dc9bbf 100644 --- a/deps/v8/src/i18n.js +++ b/deps/v8/src/i18n.js @@ -1562,7 +1562,7 @@ function initializeDateTimeFormat(dateFormat, locales, options) { var formatter = %CreateDateTimeFormat( requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved); - if (!IS_UNDEFINED(tz) && tz !== resolved.timeZone) { + if (resolved.timeZone === "Etc/Unknown") { throw MakeRangeError(kUnsupportedTimeZone, tz); } diff --git a/deps/v8/test/mjsunit/regress/regress-487322.js b/deps/v8/test/mjsunit/regress/regress-487322.js new file mode 100644 index 00000000000000..ae6da80e4473ba --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-487322.js @@ -0,0 +1,13 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Normalizes Kat{h,}mandu (chromium:487322) +df = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Katmandu'}) +assertEquals('Asia/Katmandu', df.resolvedOptions().timeZone); + +df = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Kathmandu'}) +assertEquals('Asia/Katmandu', df.resolvedOptions().timeZone); + +// Throws for unsupported time zones. +assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'Aurope/Paris'})); From 0cc8102a3c34c2ca5faf89fb3ece8a7a6f97d877 Mon Sep 17 00:00:00 2001 From: jshin Date: Mon, 4 Jan 2016 13:47:44 -0800 Subject: [PATCH 6/6] deps: backport 4e18190 from V8 upstream Original commit message: Timezone name check fix 1. Location names with more than one underscores (e.g. Ho_Chi_Minh) didn't work because of the way capturing works with repeated patterns in RE. It's now supported by changing the RE to capture the whole string and splitting on '_' in the next step. 2. Adds support for location names with a hyphen 3. Adds support for timezone ids with three parts (e.g. American/Argentina/Buenos_Aires) 4. Adds special handling of 'au', 'es' and 'of' in zone ids. They need to be kept in lowercase. (see the full list at https://en.wikipedia.org/wiki/List_of_tz_database_time_zones ) 5. Adds regression tests for all the above and make the existing tests more robust against future ICU changes. ICU canonicalizes zone names to deprecated names, but it may change. ( http://bugs.icu-project.org/trac/ticket/12044 ) BUG=364374 LOG=Y Review URL: https://codereview.chromium.org/1529363005 Cr-Commit-Position: refs/heads/master@{#33097} PR-URL: https://github.com/nodejs/node/pull/15562 --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/i18n.js | 71 +++++++++++++++---- deps/v8/src/messages.h | 6 +- .../v8/test/mjsunit/regress/regress-487322.js | 13 ---- .../mjsunit/regress/regress-crbug-364374.js | 56 +++++++++++++++ .../mjsunit/regress/regress-crbug-487322.js | 25 +++++++ 6 files changed, 146 insertions(+), 27 deletions(-) delete mode 100644 deps/v8/test/mjsunit/regress/regress-487322.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-364374.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-487322.js diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index 88682a0fa57b07..e6894d52693398 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 4 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 103 -#define V8_PATCH_LEVEL 52 +#define V8_PATCH_LEVEL 53 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/i18n.js b/deps/v8/src/i18n.js index c6675679dc9bbf..447a88dc3099a8 100644 --- a/deps/v8/src/i18n.js +++ b/deps/v8/src/i18n.js @@ -170,12 +170,25 @@ var TIMEZONE_NAME_CHECK_RE = UNDEFINED; function GetTimezoneNameCheckRE() { if (IS_UNDEFINED(TIMEZONE_NAME_CHECK_RE)) { - TIMEZONE_NAME_CHECK_RE = - new GlobalRegExp('^([A-Za-z]+)/([A-Za-z]+)(?:_([A-Za-z]+))*$'); + TIMEZONE_NAME_CHECK_RE = new GlobalRegExp( + '^([A-Za-z]+)/([A-Za-z_-]+)((?:\/[A-Za-z_-]+)+)*$') } return TIMEZONE_NAME_CHECK_RE; } +/** + * Matches valid location parts of IANA time zone names. + */ +var TIMEZONE_NAME_LOCATION_PART_RE = UNDEFINED; + +function GetTimezoneNameLocationPartRE() { + if (IS_UNDEFINED(TIMEZONE_NAME_LOCATION_PART_RE)) { + TIMEZONE_NAME_LOCATION_PART_RE = + new GlobalRegExp('^([A-Za-z]+)((?:[_-][A-Za-z]+)+)*$'); + } + return TIMEZONE_NAME_LOCATION_PART_RE; +} + /** * Adds bound method to the prototype of the given object. */ @@ -672,6 +685,34 @@ function toTitleCaseWord(word) { %StringToLowerCase(%_CallFunction(word, 1, StringSubstr)); } +/** + * Returns titlecased location, bueNos_airES -> Buenos_Aires + * or ho_cHi_minH -> Ho_Chi_Minh. It is locale-agnostic and only + * deals with ASCII only characters. + * 'of', 'au' and 'es' are special-cased and lowercased. + */ +function toTitleCaseTimezoneLocation(location) { + var match = %_CallFunction(location, GetTimezoneNameLocationPartRE(), StringMatch); + if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, location); + + var result = toTitleCaseWord(match[1]); + if (!IS_UNDEFINED(match[2]) && 2 < match.length) { + // The first character is a separator, '_' or '-'. + // None of IANA zone names has both '_' and '-'. + var separator = %_CallFunction(match[2], 0, 1, StringSubstring); + var parts = %_CallFunction(match[2], separator, StringSplit); + for (var i = 1; i < parts.length; i++) { + var part = parts[i] + var lowercasedPart = %StringToLowerCase(part); + result = result + separator + + ((lowercasedPart !== 'es' && + lowercasedPart !== 'of' && lowercasedPart !== 'au') ? + toTitleCaseWord(part) : lowercasedPart); + } + } + return result; +} + /** * Canonicalizes the language tag, or throws in case the tag is invalid. */ @@ -1723,8 +1764,8 @@ addBoundMethod(Intl.DateTimeFormat, 'v8Parse', parseDate, 1); /** - * Returns canonical Area/Location name, or throws an exception if the zone - * name is invalid IANA name. + * Returns canonical Area/Location(/Location) name, or throws an exception + * if the zone name is invalid IANA name. */ function canonicalizeTimeZoneID(tzID) { // Skip undefined zones. @@ -1739,16 +1780,22 @@ function canonicalizeTimeZoneID(tzID) { return 'UTC'; } - // We expect only _ and / beside ASCII letters. - // All inputs should conform to Area/Location from now on. + // TODO(jshin): Add support for Etc/GMT[+-]([1-9]|1[0-2]) + + // We expect only _, '-' and / beside ASCII letters. + // All inputs should conform to Area/Location(/Location)* from now on. var match = %_CallFunction(tzID, GetTimezoneNameCheckRE(), StringMatch); - if (IS_NULL(match)) throw MakeRangeError(kExpectedLocation, tzID); + if (IS_NULL(match)) throw MakeRangeError(kExpectedTimezoneID, tzID); + + var result = toTitleCaseTimezoneLocation(match[1]) + '/' + + toTitleCaseTimezoneLocation(match[2]); - var result = toTitleCaseWord(match[1]) + '/' + toTitleCaseWord(match[2]); - var i = 3; - while (!IS_UNDEFINED(match[i]) && i < match.length) { - result = result + '_' + toTitleCaseWord(match[i]); - i++; + if (!IS_UNDEFINED(match[3]) && 3 < match.length) { + var locations = %_CallFunction(match[3], '/', StringSplit); + // The 1st element is empty. Starts with i=1. + for (var i = 1; i < locations.length; i++) { + result = result + '/' + toTitleCaseTimezoneLocation(locations[i]); + } } return result; diff --git a/deps/v8/src/messages.h b/deps/v8/src/messages.h index 5c3e867933ce44..1b6f393871897f 100644 --- a/deps/v8/src/messages.h +++ b/deps/v8/src/messages.h @@ -261,7 +261,11 @@ class CallSite { T(UnsupportedSuper, "Unsupported reference to 'super'") \ /* RangeError */ \ T(DateRange, "Provided date is not in valid range.") \ - T(ExpectedLocation, "Expected Area/Location for time zone, got %") \ + T(ExpectedTimezoneID, \ + "Expected Area/Location(/Location)* for time zone, got %") \ + T(ExpectedLocation, \ + "Expected letters optionally connected with underscores or hyphens for " \ + "a location, got %") \ T(InvalidArrayBufferLength, "Invalid array buffer length") \ T(InvalidArrayLength, "Invalid array length") \ T(InvalidCodePoint, "Invalid code point %") \ diff --git a/deps/v8/test/mjsunit/regress/regress-487322.js b/deps/v8/test/mjsunit/regress/regress-487322.js deleted file mode 100644 index ae6da80e4473ba..00000000000000 --- a/deps/v8/test/mjsunit/regress/regress-487322.js +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2015 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Normalizes Kat{h,}mandu (chromium:487322) -df = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Katmandu'}) -assertEquals('Asia/Katmandu', df.resolvedOptions().timeZone); - -df = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Kathmandu'}) -assertEquals('Asia/Katmandu', df.resolvedOptions().timeZone); - -// Throws for unsupported time zones. -assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'Aurope/Paris'})); diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-364374.js b/deps/v8/test/mjsunit/regress/regress-crbug-364374.js new file mode 100644 index 00000000000000..bb554f1e44f3b3 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-364374.js @@ -0,0 +1,56 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Intl) { + // chromium:364374 + + // Locations with 2 underscores are accepted and normalized. + // 'of' and 'es' are always lowercased. + df = new Intl.DateTimeFormat('en-US', {'timeZone': 'eUrope/isLe_OF_man'}) + assertEquals('Europe/Isle_of_Man', df.resolvedOptions().timeZone); + + df = new Intl.DateTimeFormat('en-US', {'timeZone': 'africa/Dar_eS_salaam'}) + assertEquals('Africa/Dar_es_Salaam', df.resolvedOptions().timeZone); + + df = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/port_of_spain'}) + assertEquals('America/Port_of_Spain', df.resolvedOptions().timeZone); + + // Zone ids with more than 2 parts are accepted and normalized. + df = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/north_Dakota/new_salem'}) + assertEquals('America/North_Dakota/New_Salem', df.resolvedOptions().timeZone); + + // 3-part zone IDs are accepted and normalized. + // Two Buenose Aires aliases are identical. + df1 = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/aRgentina/buenos_aIres'}) + df2 = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/Argentina/Buenos_Aires'}) + assertEquals(df1.resolvedOptions().timeZone, df2.resolvedOptions().timeZone); + + df2 = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/Buenos_Aires'}) + assertEquals(df1.resolvedOptions().timeZone, df2.resolvedOptions().timeZone); + + df1 = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/Indiana/Indianapolis'}) + df2 = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/Indianapolis'}) + assertEquals(df1.resolvedOptions().timeZone, df2.resolvedOptions().timeZone); + + // ICU does not recognize East-Indiana. Add later when it does. + // df2 = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/East-Indiana'}) + // assertEquals(df1.resolvedOptions().timeZone, df2.resolvedOptions().timeZone); + + + // Zone IDs with hyphens. 'au' has to be in lowercase. + df = new Intl.DateTimeFormat('en-US', {'timeZone': 'America/port-aU-pRince'}) + assertEquals('America/Port-au-Prince', df.resolvedOptions().timeZone); + + // Accepts Ho_Chi_Minh and treats it as identical to Saigon + df1 = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Ho_Chi_Minh'}) + df2 = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Saigon'}) + assertEquals(df1.resolvedOptions().timeZone, df2.resolvedOptions().timeZone); + + // Throws for invalid timezone ids. + assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'Europe/_Paris'})); + assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'America/New__York'})); + assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'America//New_York'})); + assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'America/New_York_'})); + assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'America/New_Y0rk'})); +} \ No newline at end of file diff --git a/deps/v8/test/mjsunit/regress/regress-crbug-487322.js b/deps/v8/test/mjsunit/regress/regress-crbug-487322.js new file mode 100644 index 00000000000000..a2a2189278876b --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-crbug-487322.js @@ -0,0 +1,25 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +if (this.Intl) { + // Normalizes Kat{h,}mandu (chromium:487322) + // According to the IANA timezone db, Kathmandu is the current canonical + // name, but ICU got it backward. To make this test robust against a future + // ICU change ( http://bugs.icu-project.org/trac/ticket/12044 ), + // just check that Kat(h)mandu is resolved identically. + df1 = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Katmandu'}) + df2 = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Kathmandu'}) + assertEquals(df1.resolvedOptions().timeZone, df2.resolvedOptions().timeZone); + + // Normalizes Ulan_Bator to Ulaanbaatar. Unlike Kat(h)mandu, ICU got this + // right so that we make sure that Ulan_Bator is resolved to Ulaanbaatar. + df = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Ulaanbaatar'}) + assertEquals('Asia/Ulaanbaatar', df.resolvedOptions().timeZone); + + df = new Intl.DateTimeFormat('en-US', {'timeZone': 'Asia/Ulan_Bator'}) + assertEquals('Asia/Ulaanbaatar', df.resolvedOptions().timeZone); + + // Throws for unsupported time zones. + assertThrows(() => Intl.DateTimeFormat(undefined, {timeZone: 'Aurope/Paris'})); +} \ No newline at end of file